Repository navigation
PingPong Q&A helps communities share and build knowledge in a simple, organized way. By making it easy to ask questions, find answers, and recognize contributions, it encourages people to engage and learn together. With smart search, badges, and an interface that works on any device, the platform makes knowledge easier to discover, trust, and keep for the long term.
This artifact describes the final product, including installation, usage, and implementation details.
The product Docker image can be run with:
docker run -d --name lbaw2522 -p 8001:80 gitlab.up.pt:5050/lbaw/lbaw2526/lbaw2522The application will be available at http://localhost:8001.
To stop and remove the container:
docker stop lbaw2522
docker rm lbaw2522Administration URL: http://localhost:8001/admin
| Username | Password |
|---|---|
| admin | 12345678 |
| Type | Username | Password |
|---|---|---|
| moderator | mod | 12345678 |
| basic account | simao | 12345678 |
| basic account | raul | 12345678 |
| basic account | alex | 12345678 |
| basic account | dinis | 12345678 |
The application implements help primarily through contextual guidance and inline feedback, designed to assist users directly at the point of interaction, supplemented by dedicated informational pages.
In complex forms, such as the Edit Profile page, helper text is displayed immediately below input fields to clarify constraints.
Example: Below the "Bio" field, the text "Maximum 500 characters" guides the user on length limits. Below "Display Name", users are reminded that "This is how your name will appear to other users".
When lists (such as "Followed Tags" or "My Questions") are empty, the application does not simply show a blank space. Instead, it displays a helpful message explaining the feature and provides a call-to-action button (e.g., "Browse Tags" or "Ask a Question") to guide the user on how to populate that section.
After performing actions like Upvoting, Posting an Answer, or Updating Profile, the system provides immediate visual feedback via "Toast" notifications (pop-ups) at the bottom of the screen. This confirms to the user that the system processed their request successfully or explains why it failed.
A static FAQ (Frequently Asked Questions) page is accessible from the footer. It explains core platform mechanics, such as how the Reputation system works and how to earn badges.
In the Comment Controller, user input for comments is validated and sanitized, trimming whitespaces and collapsing excessive newlines, preventing spam and formatting abuse:
<?php
$validated = $request->validate([
'body' => 'required|string|max:300',
]);
return preg_replace("/(\r?\n){3,}/", "\n\n", trim($validated['body']));
In the Register Controller, fields are strictly validated, ensuring only valid, unique, and properly formatted data is accepted:
<?php
$request->validate([
'username' => 'required|string|max:250|unique:users',
'email' => 'required|email|max:250|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
In Moderator Controller, reasons for warnings/suspensions are sanitized, preventing excessively long or empty reasons, reducing risk of abuse:
<?php
$request->validate([
'reason' => 'required|string|max:1000',
]);
In forms (e.g. Register Account), input was sanitized enforcing format, length, and required fields before submission:
<input type="email" name="email" required maxlength="250" />
<input type="password" name="password" required minlength="6" />
In text boxes (e.g. Edit Profile Bio), maximum length was enforced, preventing users from entering more than 500 characters in their bio:
<textarea id="bio" name="bio" rows="4" maxlength="500"></textarea>
In ajax.js, forms are disabled if fields are empty or unchanged, preventing invalid or empty submissions via JavaScript:
const postAnswerForm = document.querySelector('.ajax-post-answer');
if (postAnswerForm) {
postAnswerForm.addEventListener('submit', async function (e) {
e.preventDefault();
const textarea = postAnswerForm.querySelector('textarea');
if (!textarea.value.trim()) return; // Prevent empty answers
// ...submit via fetch
});
}
To confirm the accessibility and usability of our application, we filled the provided checklist, whose results can be found below:
To confirm the compliance of our application with web standards, we validated the HTML and CSS of the central page of our product, the Question page, using the official W3C validation tools.
The HTML validation was performed using the W3C Markup Validation Service, while the CSS validation was carried out using the W3C CSS Validation Service. The resulting validation reports were exported as PDF files and uploaded to the group’s repository. The reports can be accessed through the links below:
There were significant revisions made to ensure the best product possible and prioritize out time and effort into the features that we considered more important.
As development progressed, we refined our initial design artifacts to better reflect the final implementation:
The sitemap was updated to match the final navigation structure. We refined the Admin Area by connecting the Homepage to a central Admin Dashboard, which then links to the specific management pages (Content Moderation, Tags Management, and User Management). We also expanded the Q&A Library to explicitly include the 'Feed', 'Recent Questions', and 'Top Questions' pages.
Moderation: Added warnings and suspensions tables to support robust moderation actions (US44).
User Preferences: Added a notification_preferences column to the users table to allow granular control over email and in-app alerts (US223).
Search: Added search_vector columns to question and answer tables to support high-performance full-text search (US12).
Auth & Security: Added google_id, github_id for OAuth, is_blocked for access control, and a password_reset_tokens table.
We decided that for our convenience it made more sense to assign user stories in a different way than originally planned. We reassigned some user stories so two very similar features would be assigned to the same developer. Here is a list of the changes:
- Changed US02 to Simão
- Changed US04 to Raul
- Changed US13 to Raul
- Changed US17 to Simão
- Changed US19 to Dinis
- Changed US29 to Alexandre
- Changed US34 to Raul
- Changed US36 to Raul
- Changed US218 to Simão
- Changed US211 to Simão
Over the development of PingPong Q&A, there were some user stories that we realized did not align with out product vision anymore, and didn't make sense in the scope and context of this project. These were the scrapped user stories:
- [US57] Monitor System Performance & Logs
- [US58] Configure Platform-wide Settings (notifications, email templates, security)
Due to the time constraint, we had to prioritize our time into the innovation features that truly mattered the most. We decided that these were the user stories not worth investing our time into:
- [US45] Manage and Close Duplicate / Low-quality Questions
- [US221] Appeal for Unblock / Support Contact
- [US222] Quick Reaction Emojis
We added two innovation features that were more aligned with our product vision and that were worth the time investment:
- [US117] Scroll to Top Button: As a User, I want a floating "scroll to top" button on long pages, so that I can quickly return to the top without scrolling.
- [US223] User Notification Preferences: As a User, I want to be able to choose what types of events I get notified for, so that I only get relevant notifications.
The following table lists the main external libraries and frameworks used in the PingPong project. Each library was selected to address specific technical requirements, from backend authentication to real-time notifications and frontend styling.
| Library | Reference | Description | Example Usage |
|---|---|---|---|
| Laravel Socialite | laravel/socialite v5 | OAuth authentication with Google and GitHub providers | app/Http/Controllers/GoogleController.php |
| Pusher PHP Server | pusher/pusher-php-server v7 | Real-time notifications via WebSockets for live updates | app/Events/NotificationSend.php |
| Laravel Echo | laravel-echo v2 | JavaScript library for subscribing to Pusher channels and receiving real-time events | resources/js/notifications.js |
| Tailwind CSS | tailwindcss v4 | Utility-first CSS framework for styling the user interface | resources/views/components/button.blade.php |
This subsection includes all high and medium priority user stories, sorted by order of closed date. Implementation is sequential according to the order identified below.
| US Identifier | Name | Module | Priority | Team Members | State |
|---|---|---|---|---|---|
| US02 | Sign-in / Login | M01 | High | Simão | 100% |
| US01 | Sign-up / Registration | M01 | High | Simão | 100% |
| US24 | Edit Own Profile (view & edit) | M01 | Medium | Alexandre | 100% |
| US54 | Delete User Account | M04 | Medium | Alexandre | 100% |
| US52 | Administer User Accounts (search/view/edit/create) | M04 | High | Simão | 100% |
| US22 | Post Question | M02 | High | Simão | 100% |
| US32 | Delete Question (own) | M02 | Medium | Simão | 100% |
| US34 | Delete Answer (own) | M02 | Medium | Raul | 100% |
| US23 | Post Answer | M02 | High | Raul | 100% |
| US12 | Full-text Search | M03 | High | Alexandre | 100% |
| US41 | Review and Manage Content Reports | M04 | High | Simão | 100% |
| US33 | Edit Answer (own) | M02 | Medium | Raul | 100% |
| US11 | Exact Match Search | M03 | High | Raul | 100% |
| US14 | Browse Questions (pagination/list) | M03 | High | Dinis | 100% |
| US31 | Edit Question (own) | M02 | Medium | Dinis | 100% |
| US35 | Edit Question Tags (own question) | M02 | Medium | Dinis | 100% |
| US27 | View My Answers | M01 | Medium | Raul | 100% |
| US51 | Manage Tags (create/edit/delete, synonyms) | M04 | High | Dinis | 100% |
| US26 | View My Questions | M01 | Medium | Simão | 100% |
| US13 | View Top Questions (Home Highlights) | M03 | High | Raul | 100% |
| US21 | View Personal Feed (followed tags/questions) | M03 | Medium | Dinis | 100% |
| US42 | Delete Content (questions/answers/comments) | M04 | High | Dinis | 100% |
| US211 | Comment on Answers | M02 | Medium | Simão | 100% |
| US210 | Comment on Questions | M02 | Medium | Simão | 100% |
| US110 | View Question Details | M03 | High | Simão | 100% |
| US213 | Follow Tags | M03 | Medium | Dinis | 100% |
| US43 | Edit Question Tags (global) | M04 | High | Dinis | 100% |
| US212 | Follow Question (watch) | M03 | Medium | Dinis | 100% |
| US18 | View Recent Questions | M03 | High | Raul | 100% |
| US56 | Support Administrator Accounts & Permissions | M04 | Medium | Alexandre | 100% |
| US36 | Edit Comment (own) | M02 | Medium | Raul | 100% |
| US37 | Delete Comment (own) | M02 | Medium | Raul | 100% |
| US112 | Access About / Main Features / Contacts / FAQ | M05 | Medium | Raul | 100% |
| US217 | Delete Account (request anonymization) | M01 | High | Simão | 100% |
| US28 | Vote on Questions | M02 | High | Alexandre | 100% |
| US29 | Vote on Answers | M02 | High | Alexandre | 100% |
| US15 | See Home / Landing Page | M05 | High | Simão | 100% |
| US214 | Report Content (questions/answers/comments) | M04 | Medium | Simão | 100% |
| US215 | Receive Notifications (answer to own question, votes) | M01 | Medium | Raul | 100% |
| US219 | Manage Notifications (read/snooze) | M01 | Medium | Raul | 100% |
| US55 | Block and Unblock User Accounts | M04 | High | Simão | 100% |
| US16 | Search Filters & Ordering | M03 | High | Dinis | 100% |
| US19 | Browse Questions by Tags | M03 | High | Dinis | 100% |
| US04 | OAuth API Sign-in | M01 | Medium | Raul | 100% |
| US03 | OAuth API Sign-up | M01 | Medium | Raul | 100% |
| US218 | Recover Password | M01 | Medium | Simão | 100% |
| US111 | View Public User Profiles | M03 | High | Dinis | 100% |
| US220 | Receive Badge Award Notifications | M01 | Medium | Alexandre | 100% |
| US216 | Support and View Badges / Reputation History | M01 | Medium | Alexandre | 100% |
| US38 | Mark an Answer as Accepted (question author) | M02 | High | Alexandre | 100% |
| US17 | View Notification List (public & personal) | M01 | Medium | Simão | 100% |
| US44 | Warn / Temporarily Suspend Users (moderation actions) | M04 | High | Alexandre | 100% |
| US117 | Scroll to Top Button | M05 | Low | Simão | 100% |
| US115 | Copy Link Button | M05 | Low | Alexandre | 100% |
| US114 | Dark Mode Toggle | M05 | High | Simão | 100% |
| US223 | Notification Preferences | M01 | Medium | Raul | 100% |
| US116 | Random Question | M03 | Low | Dinis | 100% |
| US45 | Manage and Close Duplicate / Low-quality Questions | M02 | Low | Simão | 0% |
| US221 | Appeal for Unblock / Support Contact | M01 | Low | Simão | 0% |
| US222 | Quick Reaction Emojis | M02 | Low | Alexandre | 0% |
This artifact corresponds to the presentation of PingPong Q&A, a collaborative knowledge-sharing platform
PingPong Q&A is where questions find answers. Ask anything, share what you know, and learn from a community that cares. Follow the topics and tags that matter to you, vote on the best answers, and watch great ideas rise to the top. Attach images to add context to your questions. Search across everything instantly. With a personalized feed based on your interests and real-time notifications, you'll never miss what matters. It's simple, fast, and beautifully designed.
Earn badges as you contribute and build your reputation within the community. Get notified the moment someone replies. Pick the best answer to highlight the most helpful response. Moderators keep conversations on track with built-in reporting and moderation tools, while admins have full control over users and content. Whether you're here to learn or to help others, PingPong makes it effortless.
The video was posted to Moodle.
Changes made to the first submission:
- Added video presentation link
GROUP2522, 22/12/2025
- Alexandre Ferreira, up202307780@up.pt
- Dinis Lima, up202304083@up.pt
- Raul Oliveira, up202303446@up.pt
- Simão Barbosa, up202306609@up.pt (editor)