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

  1. 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.
  2. 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.
  3. 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.
  4. 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.

database

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

database

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.