Always Away is a blog site, with the intention to create a community. The author is a long-term expatriot who wishes to create a safe space for users to share stories and feel a sense of camaraderie. Whether a fellow willing wanderer, displaced person, dreaming of the adventures, or simply intrigued by the stories of the migrating life - all are welcome.
View the live site by clicking HERE.
- Always Away
- Contents menu
- UX
- Accessibility
- Agile Methodology
- User Stories
- Wireframes
- Features
- C.R.U.D.
- Technologies
- Deployment
- Bugs
- Testing
- Credits
- Media
- Team Members
Always Away is a community blog site, written with the intention of sharing experiences and engaging with like-minded individuals. Here, I'll be sharing my personal journey and experiences as a long-term expatriot. Whether you're a fellow willing wanderer, displaced person, dreaming of the adventures in your own future, or simply intrigued by the stories of the migrating life, you are invited to join in to create an online community.
This site's intention is to create an online society. Always Away is meant to convey understanding, create community, and inspire a feeling of camaraderie amongst both strangers and friends.
The goal is to create a platform for online communication. The site intents to create an engaging experience to provide a modern sense of community in a growing and ever-alienating world. Where one neighborhood disappears in person, the site can provide digitally.
For citizens of the world with a thirst for adventure, the restless and onlookers alike. By having this avenue of online interaction, users will be able to get a taste of each other's experiences - hopes, dreams, struggles, heartache...everything that compiles the life of a modern-day nomad or immigrant.
The worldwide web is a vital avenue of communication for modern day travelers, nomads, displaced persons, those left behind, or for any reason long-distance relationships. Without this form of computer-generated interaction, we would still be sending snail mail that may be lost after months in transit.
To intuitively navigate the site content, create account, and begin to engage with all there is to explore.
Engage in the online community via comments or messaging to the site's author. For travellers to share their experiences and possibly make a new friend along the way.
- To create a profile page for each user to have expanded capacity for sharing and interacting.
- To implement functionality for users to post their own blog posts, including photos and text.
- To allow the site's admin to message individual users in response to their messages.
- To expand site's useability by categorizing posts and comments for users to easily be able to search for a spcific word or topic.
Back to top
This Django blog project prioritizes functionality and a positive user experience. The decision to use the standard Django template was deliberate, with a focus on providing a reliable and efficient platform for users. The choice of a standard template ensures consistency across the site, making navigation intuitive and straightforward.
-
Functionality First: The primary goal was to build a blog that meets user needs, ensuring a seamless and efficient experience.
-
Usability and Accessibility: Attention was given to usability, accessibility, and responsiveness to enhance the overall user experience.
-
Standard Template for Consistency: The use of the standard Django template was intentional, providing a clean and uniform design throughout the site.
-
Color Contrast and Design: Careful consideration was given to color contrast, and the overall color scheme contributes to a visually pleasing interface.
-
Future Customization: The standard template sets the stage for future updates or customization without compromising the existing design.
-
Efficiency in Development: Opting for the standard template allowed for efficient development, emphasizing core features without unnecessary complexity.
This approach reflects a balance between a user-centric design philosophy and efficient development practices.
Back to top
The principles of agile methodology were implemented during the project. By assigning user stories to Epics and Milestones, utilizing GitHub's Kanban board, the necessary project goals could be easliy prioritized.
- User Account Management
- I can register an account so that I can comment and like.
- I can log in to my account and see my messages so that keep track of conversations with admin.
- I can edit my comments so that I can more deeply interact with the community.
- I can delete my own comments so that change my mind about a comment.
- Content Viewing and Interaction
- I can view a paginated list of pages so that I can easily select a page to view.
- I can view a list of posts so that I can select one to read.
- I can click on a post so that I can read the full text.
- I can leave comments on a post so that I can be involved in the conversation.
- I can view comments on an individual post so that I can read the conversation.
- I can like or unlike a post so that I can interact with the content.
- I can view the number of likes on each post so that I can see which is the most popular or viral.
- Messaging System
- I can create a draft message and save without sending so that I can take my time formulating a message over more than one site visit/login.
- I can send a message to the admin so that I can interact with the creator of the blog.
- I can delete messages so that I can clean out my inbox.
- Content Creation and Management (Admin)
- Admin can view comments on an individual post so that they can read the conversation.
- Admin can leave comments on a post so that they can be involved in the conversation.
- Admin can approve or disapprove comments so that they can filter out objectionable comments.
- Admin can delete messages so that they can clean out their inbox.
- Admin can view the number of likes on each post so that they can see which is the most popular or viral.
- Admin can create draft posts so that they can finish writing the content later.
- Admin can create, read, update, and delete posts so that they can manage blog content.
The following User stories have not yet been implemented. They remain in the repository for the purpose of organizing future goals and projects - to expand and enhance the blog site.
- I can make a blog post
- I can utilize a search capability so that I can easily locate specific topics or posts
- I can organize messages by category so that I can quickly search for a message I want to find
- I can upvote on comments so that earn Karma points, eventually rewarding me with badges or digital trophies
- I can mark a message as read so that my account can keep track for me if I have read a message or not
- I can use a reply function on messages so that I can continue a string of messages with admin
- I can utilize a search capability so that I can easily locate specific topics or posts
- I can categorize posts into sub-threads so that keep multiple posts organized
- I can send message to Users from admin panel so that I can more personally interact with site Users
- I can receive notifications so that I can see when someone likes or comments on my post
Back to top
The combination of a textual mindmap and a Lucidchart flowchart strikes a balance between clarity and visual representation. The textual mindmap ensures a quick, accessible overview, while the Lucidchart flowchart adds depth to user flows, fostering a comprehensive understanding of the blog's structure and interactions.
- Admin Panel
- Blog Management
- Create Blog
- Edit Blog
- Publish Blog
- Save as Draft
- Delete Blog
- Comment Supervision
- View Comments
- Message Reading
- Inbox
- Draft Inbox
- Sent Messages
- Blog Management
- Front-End User Interaction
- Home Page
- Scrollable List of Published Blogs
- Navbar
- Register/Sign Up
- Login
- Logout
- Home Page Navigation
- Authenticated User
- Inbox
- Draft Message Inbox
- Sent Messages Inbox
- Message Actions
- Send to Admin
- Save as Draft
- View Sent Messages
- Delete Messages
- Home Page
Back to top
Back to top
Back to top
- Python
- Javascript
- HTML5
- CSS3 + SVG
- Python Built-in "os" Modules
- Django
- Bootstrap + jQuery
- ElephantSQL
- Cloudinary
- Google Fonts
- Font Awesome
- GitHub:
- GitPod:
- Am I Responsive?
- Favicon.io
- Lucidchart Wireframing
- JSHint
- 'django<4' gunicorn
- dj_database_url psycopg2
- dj3-cloudinary-storage
- django-summernote
- django-allauth
- django-crispy-forms
Back to top
- Navigate to the project repository
- Top Right menu > "Fork"
- Clicking the Fork button automatically saves a copy of the repo on your own, logged-in Github page
- Navigate to the project repository
- Click on the top right, green "Code" button
- Choose one of the three options (HTTPS, SSH or GitHub CLI) and then click copy
- Open the terminal in your IDE program
- Type git clone into your terminal and paste the URL that was copied in step 3
- Hit Enter and your local clone will be created.
Alternatively - Use Gitpod:
- Navigate to the [project repository](https://github.com/KrystalCoding/always-away
- Hit the green "Gitpod" button and the project will automatically open up for you
- Create Heroku account
- Install Django & Gunicorn via terminal command:
pip3 install 'django<4' gunicorn
- Install Django database & psycopg:
pip3 install dj_database_url psycopg2
- Install Cloudinary:
pip3 install dj3-cloudinary-storage
- Creating the requirements.txt file with the following command:
pip3 freeze --local > requirements.txt
- My django project was created using:
django-admin startproject always-away .
- The blog app was then created with:
python3 manage.py startapp blog
- This was then added to the" "settings.py" file within the project directory
- The changes were then migrated using:
python3 manage.py migrate
- Navigate to Heroku & created a new app called "always-away"
- Add the Heroku Postgres database to the Resources tab
- Navigate to the Settings tab and add the following key/value pairs to the configvars:
- key: SECRET_KEY | value: randomkey
- key: PORT | value: 8000
- key: CLOUDINARY_URL | value: API environment variable
- key: DATABASE_URL | value: value supplied by Heroku
- Create an "env.py" file
- Add the DATABASE_URL, SECRET_KEY & CLOUDINARY_URL to the "env.py" file 15.added the DATABASE_URL, SECRET_KEY & CLOUDINARY_URL to the "settings.py" file
- Add the "import os" command at the top of the "env.py" file
- Add Heroku to the ALLOWED_HOSTS in "settings.py"
- Create a "Procfile"
- Push the project to GitHub using commands
git add .
,git commit-m "Commit message"
,git push
- Use the Deploy tab in Heroku to connect to the github repository
- Click "Deploy"
Back to top
- At first, I tried to connect posting, editing, and deleting messages to the comment Model and View. Once I realized this was stupid, I learned some things and re-focused the project.
- Static Files were not included and set up properly on deployment, but that was sorted.
- Footer is not sticking to the bottom of the screen below the forms.
- Message to ask user if they are sure they want to delete a message is not functioning. Code was removed from the repo for the sake of submitting the project, but it will be implemented eventually.
- Confirmation messages to let user know their messages were saved as a draft or sent successfully are not functioning. Again, code was removed temporarily.
- Unique photo upload to the blog posts via admin panel is not functioning and I do not currently know why, though the default image is being uploaded correctly.
Back to top
- Manual testing
- Automated testing
1. As a site User I can view a paginated list of pages so that I can easily select a page to view
Step | Expected Result | Actual Result |
---|---|---|
Click on the links (or hamburger icon on smaller screens) to intuitively access pagination via navigation bar | Nav bar drop down will open on smaller screens, and links will open to their associated pages. (See below for specific link functions) | Works as expected |
Click on the Social Media icons link in the footer | Associated social media icons will load in a separate tab | Works as expected |
Click on the 'Code Institute' or 'Django Framework' logos in the side panel | External tabs with associated websites will load | Works as expected |
9. As an Admin / Authorised User I can log in so that I can access the back end of the site
Step | Expected Result | Actual Result |
---|---|---|
Visit the admin page | After verifying admin login credentials, gain access to back end | Works as expected |
3. As a Site Owner I can create and save draft blog posts, publish new blog posts, and edit formerly published posts.
Step | Expected Result | Actual Result |
---|---|---|
Click on Add Post + | New Post form will appear | Works as expected |
Click on save post as draft | Post is saved in admin panel for further updates | Works as expected |
Click on publish post | New Post is published on front end for public viewing | Works as expected |
Click on edit post in admin panel | Updates are published on front end for public viewing | Works as expected |
4. As a site User, I can register a personal account, access inbox, compose messages and save as drafts for further editing, and send messages to site admin.
Step | Expected Result | Actual Result |
---|---|---|
Click on the 'Register' link in the navigation bar | Sign up page will load | Works as expected |
Click on the 'Sign in' link in the navigation bar | Login page will load | Works as expected |
Click on the 'Contact' link in the navigation bar | Send Message to Admin form will load | Works as expected |
Click on the 'Inbox' link in the navigation bar, or 'Primary Inbox' button in the Draft Inbox page | Inbox page will load | Works as expected |
Click on the 'Draft Inbox' link in the navigation bar, or from the button in the Inbox page | Draft Inbox page will load | Works as expected |
Click on the 'Sign Out' link in the navigation bar | Logout page will load | Works as expected |
2. As a site User, I can view blog post homepage, access individual posts for viewing content, comments, and likes. When logged in as a registered user, I can post my own comments and like posts.
Step | Expected Result | Actual Result |
---|---|---|
Click on 'Blog Home' and scroll to footer at bottom of page | View blog home page in full length, all the way to the footer | Works as expected |
Click on individual posts to view content, including comments and likes | Opens individual post with scrolling function | Works as expected |
Click on like button | Page refreshes and updates icon via user's action of either liking or unliking a post | Works as expected |
Write comment and post with button | Page refreshes with comment + ability for user to edit or delete their own comment | Works as expected |
5. As a site Owner, I can approve or delete user comments from blog posts.
Step | Expected Result | Actual Result |
---|---|---|
Click on 'Comments' in admin panel | Choose to approve or delete user comments | Deleting Comments Works as Expected, but during production the priority was given to Users being able to view their comments on the blog posts immediately, without having to wait for admin approval simply to post. Therefore, admin approval for User comments is no longer applicable. |
Back to top
- Python testing was done using the built in Django module, unittest.
- Javascript testing was done using JsHint.
-
setUp
- Purpose/Function: Set up a test user for use in subsequent test cases.
- How it passes: Creates a test user with a username and password.
-
create_test_post
- Purpose/Function: Helper method to create a test blog post.
- How it passes: Creates a test post with specified attributes.
-
test_create_post
- Purpose/Function: Tests if a blog post is created successfully.
- How it passes: Calls
create_test_post
and asserts that the post is created with the expected attributes.
-
test_create_comment
- Purpose/Function: Tests if a comment on a blog post is created successfully.
- How it passes: Creates a test post, creates a comment on that post, and asserts that the comment is created with the expected attributes.
-
test_comment_approval
- Purpose/Function: Tests if a comment can be marked as approved.
- How it passes: Creates a test post, creates an unapproved comment on that post, marks the comment as approved, and asserts that the comment's approval status is updated.
Back to top
-
setUp
- Purpose/Function: Set up a test user for use in subsequent test cases.
- How it passes: Creates a test user with a username and password.
-
test_post_list_view
- Purpose/Function: Tests if the post list view returns a successful response.
- How it passes: Sends a GET request to the home page and asserts a 200 status code.
-
test_post_detail_view
- Purpose/Function: Tests if the post detail view returns a successful response.
- How it passes: Creates a test post, generates the URL for the post detail view, sends a GET request, and asserts a 200 status code.
-
test_edit_blog_comment_view
- Purpose/Function: Tests if the edit blog comment view redirects appropriately.
- How it passes: Creates a test post and comment, sends a GET request to the edit blog comment view, and asserts a 302 status code.
-
test_delete_blog_comment_view
- Purpose/Function: Tests if the delete blog comment view redirects appropriately.
- How it passes: Creates a test post and comment, sends a GET request to the delete blog comment view, and asserts a 302 status code.
-
test_post_like_view
- Purpose/Function: Tests if the post like view redirects appropriately.
- How it passes: Logs in a test user, creates a test post, sends a POST request to the post like view, and asserts a 302 status code.
Back to top
-
setUp
- Purpose/Function: Set up a test user for use in subsequent test cases.
- How it passes: Creates a test user with a username and password.
-
test_post_list_url
- Purpose/Function: Tests if the post list URL returns a successful response.
- How it passes: Sends a GET request to the home page URL and asserts a 200 status code.
-
test_post_detail_url
- Purpose/Function: Tests if the post detail URL returns a successful response.
- How it passes: Creates a test post, generates the URL for the post detail view, sends a GET request, and asserts a 200 status code.
-
test_edit_blog_comment_url
- Purpose/Function: Tests if the edit blog comment URL redirects appropriately.
- How it passes: Creates a test post and comment, generates the URL for the edit blog comment view, sends a GET request, and asserts a 302 status code.
-
test_delete_blog_comment_url
- Purpose/Function: Tests if the delete blog comment URL redirects appropriately.
- How it passes: Creates a test post and comment, generates the URL for the delete blog comment view, sends a GET request, and asserts a 302 status code.
Back to top
Automated Test 1: Timeout Function
- Description: This automated test passes JSHint successfully. It utilizes vanilla JavaScript to set a timeout function, which selects the close button within an element with the class "alert" and triggers a click event after 2000 milliseconds. The code ensures automatic closure of an alert.
Step | Expected Result | Actual Result |
---|---|---|
Execute the JavaScript timeout function | The function should find the close button for an alert with the class .alert and trigger a click event after a delay of 2000 milliseconds |
Passes JSHint and works as expected. The setTimeout function triggers a click on the close button after a delay, simulating the automatic closure of an alert. |
Automated Test 2: Fade Away Function
- Description: This automated test successfully passes JSHint. It employs jQuery to fade out elements with the class "alert" after a delay of 2000 milliseconds. The use of "$" in this code is due to jQuery being embedded in HTML, indicating the successful integration of jQuery.
Step | Expected Result | Actual Result |
---|---|---|
Execute the JavaScript timeout function with jQuery | The function should select all elements with the class .alert and fade them out slowly after a delay of 2000 milliseconds |
Passes JSHint and works as expected. The setTimeout function, combined with jQuery, fades out elements with the class `.alert`` after a delay, providing a visual fade-away effect. |
Back to top
- Martina Terlevic: Code Institute Mentor and center of sanity.
- Code Institute's walkthrough Django project, called I think therefore I blog, for basic repository set up and starter Django project code.
- Clueless Biker's github project "print(STATEMENTS)" for the README.md inspiration.
- ErikHgm's github project "FireHouse Restaurant" for README.md inspiration.
- Code Institute's tutors, and fellow students on Slack for degugging
- Stack Overflow for coding solutions when I was terribly stuck.
Back to top
-
- Photos by:
- Alex Azabache
- Cottonbro Studio
- Adrian Vieriu
- James Wheeler
- Krampus Production
- Ketut Subiyanto
- Matt Barnard
- Photos by:
-
Cloudinary photo hosting platform
Name | GitHub | |
---|---|---|
Krystal Juvrud |