# PA: Product and Presentation
The Super Legit Collaborative News (SLCN) is a project headed by a small group of developers with the main goal of free, open, and accessible news sharing for and by users.
This will allow all users to view and browse all types of news and comments on any topic, with access to text search and tag selection..
## A9: Product
The product developed is a collaborative news website, where users can create, view and browse all types of news and comments on most topics, with access to text search and tag selection.
On he home page, users can find a feed with the highest rated news, with options to search for a specific one or sort them by date. There is also a personalized news feed only with news marked by tag that the user follows.
Both news and comments are able to be rated by any authenticated user, where they can be liked or disliked. A user's own reputation is the sum of the reputation of all their posted news and comments, and can be found on their profile.
The profile houses the user's information, such as their name, reputation, country of origin, profile picture, followed and following users and a list of their posted news. The user's personal information may also be edited here.
News can be posted, using a Rich Text Editor, and are comprised of a Title, Rich Text content and a selection of tags. New tags can be proposed by users and added by administrators.
A user will be notified whenever another user likes any of their news or comments.
Finally administrators can edit and delete any news, comment or profile, and have access to an admin page where they can manage the proposed tags.
### 1. Installation
final version: [link ](https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/tree/PA)
> Include the full Docker command to start the image available at the group's GitLab Container Registry using the production database.
### 2. Usage
http://lbaw2286.lbaw.fe.up.pt
Install:
```
composer install
composer require pusher/pusher-php-server
php artisan route:clear && php artisan view:clear && php artisan config:clear && php artisan cache:clear && php artisan clear-compiled
```
And to run it locally:
```
docker run -it -p 8000:80 --name=lbaw2286 -e DB_DATABASE="lbaw2286" -e DB_SCHEMA="lbaw2286" -e DB_USERNAME="lbaw2286" -e DB_PASSWORD="HfwKxxtO" git.fe.up.pt:5050/lbaw/lbaw2223/lbaw2286
```
#### 2.1. Administration Credentials
| Email | Password |
| -------- | -------- |
| admin@example.com | 1234 |
| lucas@legitmail.com | legitlucas |
#### 2.2. User Credentials
| Type | Email | Password |
| ------------- | --------- | -------- |
| basic account | andre@legitmail.com | legitandre |
### 3. Application Help
Help was implemented in the about us page, where users can click "contact us" and directly send an email to the team.
### 4. Input Validation
The input data is always validated either through javascript or html. As an example, the number of tags selected are validated through javascript functions with event listeners. The forms for search are verified through html.
### 5. Check Accessibility and Usability
The results of accessibility and usability tests using the checklists are in the following pdfs:
- Accessibility https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/blob/main/docs/checklists/accessibility_checklist.pdf
- Usability: https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/blob/main/docs/checklists/usability_checklist%20.pdf
### 6. HTML & CSS Validation
The results of the validation of the HTML and CSS code using the required tools are the following:
- For HTML we got the following results: https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/tree/main/docs/results
- For CSS the results are in: https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/tree/main/docs/CSS%20validator
### 7. Revisions to the Project
The revisions we made since the ER were the removal of the descriptions from the tags proposals, and the removal of the images from the user's database since they are now integrated into the newly implemented rich text editor. Also the ones reported before as the change from 'topics' to 'tags' in all files.
### 8. Web Resources Specification
https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/blob/main/a9_openapi.yaml
```yaml
openapi: 3.0.0
info:
version: "2.0"
title: "LBAW SLCN Web API"
description: "Web Resources Specification (A9) for SLCN"
servers:
- url: http://lbaw2286.lbaw.fe.up.pt
description: Production server
externalDocs:
description: Find more info here.
url: https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/wikis/home
tags:
- name: "M01: Authentication"
- name: "M02: Users"
- name: "M03: News"
- name: "M04: Comments"
- name: "M05: Tags"
- name: "M06: Notifications"
- name: "M07: Search"
- name: "M08: User Administration and Static Pages"
paths:
/login:
get:
operationId: R101
summary: "R101: LoginForm"
description: "Provide login form. Access: PUB"
tags:
- "M01: Authentication"
responses:
"200":
description: "Ok. Show Log-in UI10"
post:
operationId: R102
summary: "R102: Login Action"
description: "Processes the login form submission. Access: PUB"
tags:
- "M01: Authentication"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
email: # <!--- form field name
type: string
password: # <!--- form field name
type: string
required:
- email
- password
responses:
"302":
description: "Redirect after processing the login credentials."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Successful authentication. Redirect main page."
value: "/"
302Error:
description: "Failed authentication. Redirect to login form."
value: "/login"
/logout:
post:
operationId: R103
summary: "R103: Logout Action"
description: "Logout the current authenticated user. Access: USR, ADM"
tags:
- "M01: Authentication"
responses:
"302":
description: "Redirect after processing logout."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Successful logout. Redirect to main page."
value: "/"
302Failure:
description: "Failed logout. Redirect to main page."
value: "/"
/register:
get:
operationId: R104
summary: "R104: Register Form"
description: "Provide new user registration form. Access: PUB"
tags:
- "M01: Authentication"
responses:
"200":
description: "Ok. Show Sign-Up UI09"
post:
operationId: R105
summary: "R105: Register Action"
description: "Processes the new user registration form submission. Access: PUB"
tags:
- "M01: Authentication"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
username:
type: string
email:
type: string
password:
type: string
required:
- username
- email
- password
responses:
"302":
description: "Redirect after processing the new user information."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Successful authentication. Redirect to main page."
value: "/"
302Failure:
description: "Failed authentication. Redirect to login form."
value: "/login"
/profile/{id}:
get:
operationId: R201
summary: "R201: Gets a profile page of a user."
description: "Displays profile page of a user. Access: USR"
tags:
- "M02: Users"
responses:
"200":
description: "Ok. Show Profile page [UI03]"
"302":
description: "Redirect."
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "Redirect to login page."
value: "/login"
/edit_profile/{id}:
post:
operationId: R202
summary: "R202: Displays User edit page."
description: "Display edit page for a user's profile. Access: AUTH, ADM"
tags:
- "M02: Users"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"302":
description: "Redirect."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Redirect to profile edit page."
value: "/edit_profile/{id}"
302Failure:
description: "Redirect to profile page."
value: "/profile/{id}"
/api/edit_profile/{id}:
post:
operationId: R203
summary: "R203: Edits a user's profile."
description: "Processes and edits a user's profile. Access: AUTH, ADM"
tags:
- "M02: Users"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
username:
type: string
country:
type: string
email:
type: string
password:
type: string
required:
- id
- username
- country
- email
- password
responses:
"302":
description: "Redirect."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Redirect to profile page."
value: "/profile/{id}"
302Failure:
description: "Redirect to profile edit page."
value: "/edit_profile/{id}"
/change_admin/{id}:
post:
operationId: R204
summary: "R204: Changes a users admin role."
description: "Changes a users admin role. If the user is an admin, they lose the role and vice-versa. Access: ADM"
tags:
- "M02: Users"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"302":
description: "Redirect."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Redirect to profile page."
value: "/profile/{id}"
302Failure:
description: "Redirect to profile page."
value: "/profile/{id}"
/:
get:
operationId: R301
summary: "R301: Shows home feed."
description: "Obtains page with the most popular news items. Access; PUB"
tags:
- "M03: News"
responses:
"200":
description: "Ok. Show home feed [UI01]"
/news/{id}:
get:
operationId: R302
summary: "R302: Shows news item."
description: "Obtains page with the selected news item. Access; USR"
tags:
- "M03: News"
parameters:
- in: path
name: id
schema:
type: integer
required: true
responses:
"200":
description: "Ok. Show news item [UI02]"
"302":
description: "User not logged in. Redirect to login form"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to login page."
value: "/login"
/api/news:
post:
operationId: R303
summary: "R303: News creation action."
description: "Processes the new news item form submition and creates the news item. Access; USR"
tags:
- "M03: News"
requestBody:
required: true
content:
application/x-www-form-urlenconded:
schema:
type: object
properties:
title:
type: string
content:
type: string
picture:
type: object
id_author:
type: integer
required:
- title
- content
- id_author
responses:
"302":
description: "Redirect after processing new news item."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Successful news creation. Redirection to news item."
value: "/news/{id}"
302Failure:
description: "Failure in news creation. Redirection to home page."
value: "/"
/api/news/{news_id}:
post:
operationId: R304
summary: "R304: Deletes a news item"
description: "Deletes a news item; Access: AUTH, ADM"
tags:
- "M03: News"
requestBody:
required: true
content:
application/x-www-form-urlenconded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"302":
description: "Redirect after processing and deleting news item."
headers:
location:
schema:
type: string
examples:
302Sucess:
description: "Successful news deletion. Redirection to home page."
value: "/"
302Failure:
description: "Failure in news deletion. Redirection to news page."
value: "/news/{id}"
/api/news/update/:
post:
operationId: R305
summary: "R305: Edits a news item"
description: "Processes and edits a news item; Access: AUTH, ADM"
tags:
- "M03: News"
requestBody:
required: true
content:
application/x-www-form-urlenconded:
schema:
type: object
properties:
id:
type: integer
title:
type: string
content:
type: string
picture:
type: object
id_author:
type: integer
required:
- id
- title
- content
- id_author
responses:
"302":
description: "Redirect after editing news item."
headers:
location:
schema:
type: string
examples:
302Success:
description: "Successful news update. Redirection to news page."
value: "/news/{id}"
302Failure:
description: "Failure in news update. Redirection to news page."
value: "/news/{id}"
/search:
get:
operationId: R701
summary: "R701: Search for news posts or users"
description: "Search for news posts or users. Access: PUB"
tags:
- "M07: Search"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
query:
type: string
required:
- query
responses:
"302":
description: "Redirect after processing the query."
headers:
Location:
schema:
type: string
examples:
302Success:
description: "Successful search. Redirect to search results page.[UI05]"
value: "/search/{query}"
302Failure:
description: "Failed search. Redirect to home page."
value: "/"
"400":
description: "Bad Request"
/following:
get:
operationId: R306
summary: "R306: Show user curated news feed"
description: "Search for news posts or users. Access: AUTH, ADM"
tags:
- "M03: News"
responses:
"200":
description: "Ok, show curated news feed"
"302":
description: "User not logged in. Redirect to main feed"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to main feed."
value: "/"
/about_us:
get:
operationId: R801
summary: "R801: Show about us page"
description: "Shows about us page. Access: PUB"
tags:
- "M08: User Administration and Static Pages"
responses:
"200":
description: "Ok, show about us page"
/rte:
get:
operationId: R307
summary: "R307: Show rich text news creation page"
description: "Shows rich text news creation page. Access: AUTH, ADM"
tags:
- "M03: News"
responses:
"200":
description: "Ok, show rich text news create page"
"302":
description: "User not logged in. Redirect to login page"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to login page."
value: "/login"
/rte/{id}:
get:
operationId: R308
summary: "R308: Show rich text news edit page"
description: "Shows rich text news edit page. Access: AUTH, ADM"
tags:
- "M03: News"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, show rich text news edit page"
"302":
description: "User not logged in. Redirect to login page"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to login page."
value: "/login"
/api/delete_profile/{id}:
post:
operationId: R202
summary: "R202: Deletes user account"
description: "Deletes user account. Access: AUTH, ADM"
tags:
- "M02: Users"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, deletes user account"
"401":
description: "Anauthorized access"
headers:
Location:
schema:
type: string
/api/follow:
post:
operationId: R203
summary: "R202: Follows a user"
description: "Follows a user. Access: AUTH, ADM"
tags:
- "M02: Users"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id1:
type: integer
id2:
type: integer
required:
- id1
- id2
responses:
"200":
description: "Ok, Follows user"
"401":
description: "Anauthorized access"
headers:
Location:
schema:
type: string
/api/unfollow:
post:
operationId: R204
summary: "R204: unFollows a user"
description: "unFollows a user. Access: AUTH, ADM"
tags:
- "M02: Users"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id1:
type: integer
id2:
type: integer
required:
- id1
- id2
responses:
"200":
description: "Ok, follows user"
"401":
description: "Anauthorized access"
headers:
Location:
schema:
type: string
/follow_list/{id}:
get:
operationId: R205
summary: "R205: Show followed users list"
description: "Show followed users list. Access: AUTH, ADM"
tags:
- "M02: Users"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, show followed users list"
"302":
description: "User not logged in. Redirect to login page"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to login page."
value: "/login"
/api/new_comment:
post:
operationId: R401
summary: "R401: Creates a comment"
description: "Creates a comment. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id_news:
type: integer
content:
type: string
required:
- id_news
- content
responses:
"200":
description: "Ok, creates comment. Refreshes news page."
"302":
description: "User not logged in. Redirect to login page"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to login page."
value: "/login"
/api/del_comment:
post:
operationId: R402
summary: "R402: Deletes a comment"
description: "Deletes a comment. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, deletes a comment. Refreshes news page."
"302":
description: "User not logged in. Redirect to login page"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to login page."
value: "/login"
/api/edit_comment:
post:
operationId: R403
summary: "R403: Edits a comment"
description: "Edits a comment. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
content:
type: string
required:
- id
- content
responses:
"200":
description: "Ok, edits comment. Refreshes news page."
"302":
description: "User not logged in. Redirect to login page"
headers:
Location:
schema:
type: string
examples:
302Failure:
description: "User not logged in. Redirect to login page."
value: "/login"
/api/getReplies:
post:
operationId: R404
summary: "R404: Retrieves replies to a comment."
description: "Retrieves replies to a comment with AJAX. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
id_comment:
type: integer
required:
- id
- id_comment
responses:
"200":
description: "Ok, returns replies as JSON."
"401":
description: "User not logged in. Access Denied"
/api/createReply:
post:
operationId: R405
summary: "R405: Creates a reply to a comment."
description: "Creates a reply to a comment with AJAX. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
news_id:
type: integer
id_comment:
type: integer
required:
- news_id
- id_comment
responses:
"200":
description: "Ok, Reply created."
"401":
description: "User not logged in. Access Denied"
/api/editReply:
post:
operationId: R406
summary: "R406: Edits a reply to a comment."
description: "Edits a reply to a comment with AJAX. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
content:
type: string
required:
- id
- content
responses:
"200":
description: "Ok, Reply Edited Successfuly."
"401":
description: "User not logged in. Access Denied"
/api/delReply:
delete:
operationId: R407
summary: "R407: Deletes a reply to a comment."
description: "Deletes a reply to a comment with AJAX. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, Reply Deleted Successfuly."
"401":
description: "User not logged in. Access Denied"
/api/vote/newsCreate:
post:
operationId: R309
summary: "R309: Creates a vote on a news."
description: "Creates a vote on a news with AJAX. Access: AUTH, ADM"
tags:
- "M03: News"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
is_liked:
type: integer
required:
- id
- is_liked
responses:
"200":
description: "Ok, Vote Created."
"401":
description: "User not logged in. Access Denied"
/api/vote/newsUpdate:
post:
operationId: R310
summary: "R310: Updates a vote on a news."
description: "Updates a vote on a news with AJAX. Access: AUTH, ADM"
tags:
- "M03: News"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
is_liked:
type: integer
required:
- id
- is_liked
responses:
"200":
description: "Ok, Vote Updated."
"401":
description: "User not logged in. Access Denied"
/api/vote/newsDelete:
delete:
operationId: R311
summary: "R311: Deletes a vote on a news."
description: "Deletes a vote on a news with AJAX. Access: AUTH, ADM"
tags:
- "M03: News"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, Vote Deleted."
"401":
description: "User not logged in. Access Denied"
/api/vote/commentCreate:
post:
operationId: R408
summary: "R408: Creates a vote on a comment."
description: "Creates a vote on a comment with AJAX. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
is_liked:
type: integer
required:
- id
- is_liked
responses:
"200":
description: "Ok, Vote Created."
"401":
description: "User not logged in. Access Denied"
/api/vote/commentUpdate:
post:
operationId: R409
summary: "R409: Updates a vote on a comment."
description: "Updates a vote on a comment with AJAX. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
is_liked:
type: integer
required:
- id
- is_liked
responses:
"200":
description: "Ok, Vote Updated."
"401":
description: "User not logged in. Access Denied"
/api/vote/commentDelete:
delete:
operationId: R410
summary: "R410: Deletes a vote on a comment."
description: "Deletes a vote on a comment with AJAX. Access: AUTH, ADM"
tags:
- "M04: Comments"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, Vote Deleted."
"401":
description: "User not logged in. Access Denied"
/api/tag/propose:
post:
operationId: R501
summary: "R501: Creates a tag proposal."
description: "Creates a tag proposal with AJAX. Access: AUTH, ADM"
tags:
- "M05: Tags"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
type: string
required:
- name
responses:
"200":
description: "Ok, Tag Proposal Created."
"401":
description: "User not logged in. Access Denied"
/api/tag/create:
post:
operationId: R502
summary: "R502: Creates a tag and handles the proposal."
description: "Creates a tag and handles the proposal with AJAX. Access: AUTH, ADM"
tags:
- "M05: Tags"
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
required:
- id
responses:
"200":
description: "Ok, Tag Created, Proposal Handled."
"401":
description: "User not logged in. Access Denied"
/recover:
get:
operationId: R106
summary: "R106: Recover Password."
description: "Allows to change your password. Access: PUB"
tags:
- "M01: Authentication"
responses:
"302":
description: "Redirects to recover_password."
/welcome_email:
get:
operationId: R107
summary: "R107: Send Welcome Email."
description: "Sends Welcome Email. Access: PUB"
tags:
- "M01: Authentication"
responses:
"302":
description: "Email sent, redirect to main page."
/recover_password:
get:
operationId: R108
summary: "R108: Recover Password."
description: "Allows to change your password. Access: PUB"
tags:
- "M01: Authentication"
responses:
"302":
description: "Ok. Sends email and redirects to login"
/api/sendnotifications:
post:
operationId: R601
summary: "R601: Send a notification"
description: "Sends a notification using pusher. Access: AUTH, PUB"
tags:
- "M06: Notifications"
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
id:
type: integer
type:
type: string
user_id:
type: integer
receiver_id:
type: integer
required:
- id
- type
- user_id
- receiver_id
responses:
"200":
description: "Ok, Notification Sent."
"401":
description: "User not logged in. Access Denied"
/admin:
get:
operationId: R802
summary: "R802: Show Admin page"
description: "Shows the Admin page. Access: ADM"
tags:
- "M08: User Administration and Static Pages"
responses:
"302":
description: "Sends the user to the Admin Page"
```
### 9. Implementation Details
#### 9.1. Libraries Used
- [TinyMCE](https://www.tiny.cloud/tinymce/)
- Used in the create and edit page for news, allows us to use a rich text editor for its content
- Link: https://www.tiny.cloud/tinymce/
- [Pusher Notifications](https://pusher.com/)
- Used for real time notifications
- Link: https://pusher.com/
#### 9.2 User Stories
| US Identifier | Name | Module | Priority | Team Members | State |
| ------------- | ------- | ------ | ------------------------------ | -------------------------- | ------ |
| US01 | View Top News Feed | Module 3 | High | **João Teixeira**, Rui Soares | 100% |
| US02 | View News Item | Module 3 | High | **João Teixeira**, Rui Soares, Lucas Sousa, André Morais | 100% |
| US03 | Search | Module 7 | High | **João Teixeira** | 100%
| US04 | View News Item Comments | Module B | High | **Lucas Sousa**, Rui Soares | 100% |
| US05 | View Other Users' Profiles | Module 2 | Medium | **João Teixeira**, Rui Soares, Lucas Sousa | 100% |
| US06 | View News Item Tag | Module 3 | Medium | **Rui Soares**, André Morais | 100% |
| US07 | View Recent News Feed | Module 3 | Medium | **João Teixeira**, Rui Soares | 100% |
| US08 | About Us | Module 8 | Medium | **Rui Soares** | 100% |
| US09 | Contacts | Module 8 | Medium | **Rui Soares** | 100% |
| US10 | Sign-in | Module 1 | High | **Lucas Sousa**, João Teixeira, André Morais | 100% |
| US11 | Sign-up | Module 1 | High | **André Morais**, Lucas Sousa, João Teixeira | 100% |
| US12 | Recover Password | Module 1 | Medium | **Rui Soares**, João Teixeira | 100% |
| US13 | Create News Item | Module 3 | High | **Rui Soares**, João Teixeira, Lucas Sousa, André Morais | 100% |
| US14 | Sign-out | Module 1 | High | **João Teixeira**, Rui Soares | 100% |
| US15 | Edit Profile | Module 2 | High | **André Morais**, João Teixeira | 100% |
| US16 | View Personal Profile | Module 2 | High | **João Teixeira**, André Morais, Rui Soares | 100% |
| US17 | View User News Feed | Module 3 | High | **Lucas Sousa**, João Teixeira | 100% |
| US18 | Create a Comment | Module 4 | Medium | **João Teixeira**, Rui Soares, Lucas Sousa | 100% |
| US19 | Vote/Unvote on News Item | Module 3 | Medium | **Lucas Sousa**, Rui Soares | 100% |
| US20 | Vote/Unvote on Comment | Module 4 | Medium | **Lucas Sousa**, Rui Soares | 100% |
| US21 | Delete Account | Module 2 | Medium | **André Morais**, João Teixeira, Rui Soares | 100% |
| US22 | Follow/Unfollow Tags | Module 5 | Medium | **André Morais**, João Teixeira | 100% |
| US23 | Follow/Unfollow Users | Module 2 | Medium | **João Teixeira**, Lucas Sousa, Rui Soares | 100% |
| US24 | Profile Picture | Module 2 | Medium | **Rui Soares**, João Teixeira | 100% |
| US25 | Answer a Comment | Module 4 | Low | **Lucas Sousa**, Rui Soares | 100% |
| US26 | Edit News Item | Module 3 | Medium | **Rui Soares**, João Teixeira | 100% |
| US27 | Delete News Item | Module 3 | Medium | **João Teixeira**, André Morais | 100% |
| US28 | News Vote Notification | Module 6 | Medium | **Lucas Sousa**, Rui Soares | 100% |
| US29 | Edit Comment | Module 4 | Medium | **Lucas Sousa**, Rui Soares, André Morais | 100% |
| US30 | Delete Comment | Module 4 | Medium | **João Teixeira**, Rui Soares, Lucas Sousa | 100% |
| US31 | Comment Vote Notification | Module 6 | Medium | **Lucas Sousa**, Rui Soares | 100% |
| US32 | Administer User Accounts | Module 8 | High | **João Teixeira**, Lucas Sousa, Rui Soares, André Morais | 100% |
| US33 | Delete User Accounts | Module 8 | Medium | **André Morais**, João Teixeira, Rui Soares | 100% |
| US34 | Manage Content | Module 8 | Low | **André Morais**, Lucas Sousa, Rui Soares, João Teixeira | 100% |
| US35 | Manage Tags Proposals | Module 8 | Low | **João Teixeira**, Lucas Sousa, André Morais | 100% |
---
## A10: Presentation
### 1. Product presentation
Super Legit Collaborative News(SLCN) is a collaborative news website, where users can create, view, rate news and comments on those news. It features top, recent and curated news feeds, aswell as search options for news, users and tags. Speaking of tags, users can follow tags and propose new ones.
Users have access to a profile, housing their public, editable information, aswell as their posts and reputation. Reputation is the sum of the votes from their news and comments. Everytime another user likes their news or comments, they get a realtime popup notification.
Finally administrators can edit and delete any news, comment or profile, and have access to an admin page where they can manage the proposed tags.
URL to the product: http://lbaw2286.lbaw.fe.up.pt
### 2. Video presentation
https://git.fe.up.pt/lbaw/lbaw2223/lbaw2286/-/blob/main/docs/lbaw2286.mp4

## Revision history
Changes made to the first submission:
- Changed content of news to rich text
***
GROUP2286, 03/01/2023
- André Morais, up202005303@edu.fe.up.pt (editor)
- João Teixeira, up202005437@edu.fe.up.pt
- Lucas Sousa, up202004682@edu.fe.up.pt
- Rui Soares, up202103631@edu.fe.up.pt