Flocker Post and Data
Share code that enables requests. Show data that is initialized in backend and displayed in frontend.
- Visual Recap
- Key Frontend Fetch Highlights
- Key Backend Data Definitions
- Backend Preparations
- Backend Testing
Visual Recap
+---------------+
| GitHub Pages |
| Design, Layout|
| Frontend |
+---------------+
|
| User presentation, style
|
v
+--------------+
| JavaScript |
| Logic/Events |
+--------------+
|
| JS Functionality, interactivity
| Sends API request
v
+----------------+
| Python / Flask |
| Backend |
+----------------+
|
| Python Server-Side API Processing
| Communicate with Data Services
| Replies with Response
v
+----------------+
| SQL Alchemy |
| Store Data |
+----------------+
Text Representation Walk-through
- GitHub Pages (Frontend):
- Design, Layout: The frontend is hosted on GitHub Pages, where the design and layout are defined.
- User Presentation, Style: This layer is responsible for presenting the user interface and applying styles.
- JavaScript (Logic/Events):
- JS Functionality, Interactivity: JavaScript adds functionality and interactivity to the frontend.
- Sends API Request: When a user interacts with the frontend, JavaScript sends an API request to the backend.
- Python / Flask (Backend):
- Python Server-Side API Processing: The Flask backend processes the API requests sent from the frontend.
- Communicate with Data Services: The backend communicates with data services to fetch or store data.
- Replies with Response: After processing the request, the backend sends a response back to the frontend.
- SQL Alchemy (Store Data):
- Store Data: SQL Alchemy is used to interact with the database, storing and retrieving data as needed.
- Relational Model: The relational model consists of Sections containing Groups, which have Channels for Posts, with Users acting as Group moderators and Post contributors.
Key Frontend Fetch Highlights
Here is a breakdown of the key steps in frontend. This can be altered to your Section, Groups, and Channels. After table there are code snippets that highlight supporting elements in code.
Step | Task | User Action | Compute Action |
---|---|---|---|
1 | Present Select Group and Channel | Fetch groups | |
2 | Pick group from dropdown | User picks from dropdown | Fetch associated channels |
3 | Pick channel from dropdown | User picks from dropdown | |
4 | Press “Select” Button | User clicks “Select” Button | Fetches and displays associated posts |
5 | Present Post Form | User inputs post details | |
6 | Press “Add Post” Button | User clicks “Add Post” Button | Handles add request with post action to backend |
7 | Display response | Fetches and displays associated posts with new item |
Fetch Groups
“Home Page” is the Section Name
Fetch groups for “Home Page” section_name
const response = await fetch(`${pythonURI}/api/groups/filter`, {
...fetchOptions,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ section_name: "Home Page" })
});
Prepare Groups dropdown
Reponse json contains is set to groups
Populate the group dropdown by appending fetched groups to groupSelect.
const groups = await response.json();
const groupSelect = document.getElementById('group_id');
groups.forEach(group => {
const option = document.createElement('option');
option.value = group.name;
option.textContent = group.name;
groupSelect.appendChild(option);
});
Fetch Associated channels
The goup_name passed in body provides association.
Fetch channels based on the selected group_name.
const response = await fetch(`${pythonURI}/api/channels/filter`, {
...fetchOptions,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ group_name: groupName })
});
Handles add request
Form data is input by user: title, comment
Fetch to backend adds data to persistent storage (database).
const postData = {
title: title,
comment: comment,
channel_id: channelId
};
const response = await fetch(`${pythonURI}/api/post`, {
...fetchOptions,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
});
Fetch and Display Posts
The channel_id provides association or filter as data is fetched from persistent storage.
The postData response contains JSON of posts that are formatted and appended to DOM postItem and detailsDiv.
cconst response = await fetch(`${pythonURI}/api/posts/filter`, {
...fetchOptions,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ channel_id: channelId })
});
const postData = await response.json();
postData.forEach(postItem => {
const postElement = document.createElement('div');
postElement.className = 'post-item';
postElement.innerHTML = `
<h3>${postItem.title}</h3>
<p><strong>Channel:</strong> ${postItem.channel_name}</p>
<p><strong>User:</strong> ${postItem.user_name}</p>
<p>${postItem.comment}</p>
`;
detailsDiv.appendChild(postElement);
});
Key Backend Data Definitions
Defining data relationship provides the ability to create customized posts for your Flocker social media categories.
File | Purpose | Relationship |
---|---|---|
model/section.py | Represents social media topic | Contains multiple Groups |
model/group.py | Represents a collection of channels | Belongs to a Section, contains Channels |
model/channel.py | Represents a communication channel | Belongs to a Group, contains Posts |
model/post.py | Represents individual messages | Belongs to a Channel |
model/user.py | Represents users | Acts as Group moderators and Post contributors |
Static Data
Sometimes data is created statically to get us off the ground. Ultimately you should build Admin or Moderator access screens to add data through the frontend. But, for now we will add static data for Section, Group, and Channel.
Add Section data
This is complete Section data sccording to initial requirements provided by students.
This data should be ready for Night at the Museum reviews.
s1 = Section(name='Home Page')
s2 = Section(name='Shared Interest')
s3 = Section(name='Create and Compete')
s4 = Section(name='Vote for the GOAT')
s5 = Section(name='Share and Care')
s6 = Section(name='Rate and Relate')
sections = [s1, s2, s3, s4, s5, s6]
Add Group data
Samples how are for Home Page, Shared Interests
These should mirror your team requirements. Make a new group += [...]
array and define your Group content. Scum Master of Scrum Master and Integrator of Integrators should help coordinate. Keep work in distinct code block to avoid merge errors and make it easily identifiable.
# Home Page Groups
home_page_section = Section.query.filter_by(_name='Home Page').first()
groups = [
Group(name='General', section_id=home_page_section.id, moderators=[User.query.get(1)]),
Group(name='Support', section_id=home_page_section.id, moderators=[User.query.get(1)])
]
# Shared Interest Groups
shared_interest_section = Section.query.filter_by(_name='Shared Interest').first()
groups += [
Group(name='Limitless Connections', section_id=shared_interest_section.id, moderators=[User.query.get(1)]),
Group(name='DNHS Football', section_id=shared_interest_section.id, moderators=[User.query.get(1)]),
Group(name='School Subjects', section_id=shared_interest_section.id, moderators=[User.query.get(1)]),
Group(name='Music', section_id=shared_interest_section.id, moderators=[User.query.get(1)]),
Group(name='Satire', section_id=shared_interest_section.id, moderators=[User.query.get(1)]),
Group(name='Activity Hub', section_id=shared_interest_section.id, moderators=[User.query.get(1)])
]
Add each Channel to a Group
Samples for Home Page Groups, Shared Interests Groups
These could be created statically (as shown) or dynamically (through frontend) according to your skill and implementation requirements. The best practice is to get something working easily and be ready for N@tM. The Agile Scrum philosopy would be do what is easiest first and then start to iterate according to your eventual objectives.
Make a new array for your channels. Then add your array to the channels variable. As stated before, keep work in distinct code block to avoid merge errors and make it easily identifiable.
# Home Page Channels
general = Group.query.filter_by(_name='General').first()
support = Group.query.filter_by(_name='Support').first()
home_page_channels = [
Channel(name='Announcements', group_id=general.id),
Channel(name='Events', group_id=general.id),
Channel(name='FAQ', group_id=support.id),
Channel(name='Help Desk', group_id=support.id)
]
# Shared Interest Channels
limitless_connection = Group.query.filter_by(_name='Limitless Connections').first()
dnhs_football = Group.query.filter_by(_name='DNHS Football').first()
school_subjects = Group.query.filter_by(_name='School Subjects').first()
music = Group.query.filter_by(_name='Music').first()
satire = Group.query.filter_by(_name='Satire').first()
activity_hub = Group.query.filter_by(_name='Activity Hub').first()
shared_interest_channels = [
Channel(name='Penpal Letters', group_id=limitless_connection.id),
Channel(name='Game vs Poway', group_id=dnhs_football.id),
Channel(name='Game vs Westview', group_id=dnhs_football.id),
Channel(name='Math', group_id=school_subjects.id),
Channel(name='English', group_id=school_subjects.id),
Channel(name='Artist', group_id=music.id),
Channel(name='Music Genre', group_id=music.id),
Channel(name='Humor', group_id=satire.id),
Channel(name='Memes', group_id=satire.id),
Channel(name='Irony', group_id=satire.id),
Channel(name='Cyber Patriots', group_id=activity_hub.id),
Channel(name='Robotics', group_id=activity_hub.id)
]
channels = home_page_channels + shared_interest_channels
Backend Preparations
Modify schema and make your custom initialization
The examples code added initializes data. The scripts/db_init.py
file updates schema and initializes data. These operations will destroy data that has been previously added.
Backend Testing
Build requests and see JSON response in Postman
A starter file of requests has been prepared to assist in testing backend api’s Flocker Local.postman_collection.json
. Import this file into Postman.