Skip to content

Design and Planning

JW Choi edited this page Dec 9, 2022 · 14 revisions

Cago

Design and Planning Document

Document Revision History

Version MM-DD-YYYY Comment
1.0 10-29-2022 Initial version
1.1 11-12-2022 Updated for sprint 3
1.2 11-26-2022 Updated for sprint 4
1.3 12-09-2022 Updated for sprint 5

Changelog

Sprint 3

  • Slightly modified "Frontend Pages" diagram.
  • Added "Frontend Details" section.
  • Updated "Database Schema" section - added ManagedCafe model and modified the fields of Cafe model.
  • Deleted unnecessary methods in "API List" section.
  • Added "API Details" section.
  • Added "Subteams" section in "Implementation Plan" section.
  • Updated "Plan Table" and added "Dependencies" column.

Sprint 4

  • "Frontend Details" is extended.
    • "/cafes"
    • "/admin/dashboard"
    • "/admin/register-cafe"
    • "/admin/register-dashboard/[cafe_id]"
  • Implementation Plan
    • "Cago admin header" is changed from partia" to completed.
    • "/cafes", "admin/register-cafe", and "/admin/dashboard" are completed.
    • "/admin/dashboard/:id" is partialy completed.
    • "/cafes/:id/info" and "/admin/dashboard/:id/info" are delayed to sprint 5.

Sprint 5

  • "Frontend Details" is extended.

    • "/cafes/[cafe_id]/info"
    • "/cafes/[cafe_id]/menu"
    • "/cafes/[cafe_id]/reviews"
    • "/cafes/[cafe_id]/reviews/create"
    • "/cafes/[cafe_id]/board"
    • "/admin/dashboard/[cafe_id]/info"
    • "/admin/dashboard/[cafe_id]/menu"
    • "/admin/dashboard/[cafe_id]/reviews"
    • "/admin/dashboard/[cafe_id]/board"
    • "/admin/dashboard/[cafe_id]/board/post"
    • "/admin/dashboard/[cafe_id]/add-pictures"
  • Implementation Plan

    • "Cago header" and "/admin/dashboard/:id" are changed from partial to completed.
    • All the remaining tasks are completed.

System Architecture

Cloud Network Architecture

Cloud Network Architecture drawio Cago is deployed on the cloud service AWS. We separate public subnets and private subnets so the web services placed in the private subnets cannot be directly accessed by the Internet. Instead we set up a load balancer on the public subnets, where Internet gateway is located, so it can route each services i.e. React and Django applications by specific path or subdomain. The deployment is just simply upstreaming a new Docker image to ECR (Elastic Container Registry), then our ECS (Elastic Container Service) cluster initializes Fargate services which runs our applications by running the Docker image as a container.

Application Architecture

Cago System Architecture drawio

The web server runs open-source React web framework Next.js, and the web application server runs Django application, which is served by Nginx HTTP server and Gunicorn WSGI. The database server (which is deployed by AWS RDS) runs PostgreSQL database. Here the frontend application isn"t just a static file bundles, so API request to the web application server can be directly performed by the browser or the Next.js server.

Design Details

Frontend Pages

User Authorization

frontend_auth

Cago

frontend_cago

Cago Admin

frontend_cago_admin

Frontend Details

/auth/signup

  • RequireLogout: Renders children only if the user is logged out, else redirect to the page in redirect query parameter.
  • SignUpForm: Form which has two stages: "email" and "password". On "email" stage, email field appears. When the user submit the form then the stage is changed to "password". Email uniqueness validation is conducted by checking the error response of POST /auth/signup/. On "password" stage, password and password_confirm fields appear. Submit to POST /auth/signup/. After that, call POST /auth/login to log in the user.

/auth/login

  • RequireLogout
  • LoginForm: Form which has two fields: email and password. Submit to POST /auth/login/.
  • There is a link to "/auth/signup", preserving the query parameters.

/create-profile

  • RequireLogin: Renders children only if the user is logged in, else redirect to /auth/login with redirect query parameter set to the current page.
  • CreateProfileForm: Can upload avatar image, and set a display name. Submit to POST /customer-profile/.
  • Redirects to the page in redirect query parameter if the user already has a customer profile.

/cafes

  • RequireProfile: Renders children only if the user is logged out, or has a profile. If not redirect to /create-profile with redirect query paramter set to the current page.
  • CafeMaps
    • KakaoMap : Dynamically load Kakao maps script, then create "Map" object to represent the map displayed on the browser. Using the browser"s Geolocation API, get the devices" location and set it as an initially the map is centered at the current location. Also provides various callbacks: onClick, onCenterChange, onCreate, onCurrentLocationChange. When displayCurrentLocation is set, the red marker is displayed at the current location on the map.
    • CafeOverlay : Overlay to show when the marker of a cafe is selected. Displays address and phone number for unmanaged cafes, and for managed cafes its representative image, crowdedness, and "자세히" button is displayed additionaly. Crowdedness is represeneted in progress bar with 3 discrete steps. "자세히" button redirects to "/cafes/[cafe_id]/info" page.
    • API GET /cafes/?location is called here. The cafe listing is based on cafeSearchCenter state. Initially it is set to the current location, and if the user clicks "다시 검색하기" button it is set to the current center of the map. Then refetch the cafes list, and display its marker on the map. Red marker and gray marker respectively represent managed cafe and unmanaged cafe. If the marker is clicked, the center of the map is moved to properly position the corresponding CafeOverlay.

/cafes/[cafe_id]/info

  • RequireProfile
  • CagoButtonGroup: display: fixed component that contains links to "/cafes/[cafe_id]/info", "/cafes/[cafe_id]/menu", "/cafes/[cafe_id]/reviews", "/cafes/[cafe_id]/board".
  • ImageView: Responsible to display the images, mainly those belongs to the managed cafes. Shows one of the images at once, and have button controls to navigate through the images. The parent component can access the current index of the images by onIndexChange: (index:number) => void callback in the props.
  • CafeIntroduction: Displays the introduction of the cafe (in the props). If editable flag is true, the user can edit the message and call PATCH /cafes/:cafe_id/ to edit the introduction.
  • StatisticsContainer: Displays the list of name-value pairs with style. In this page, displays the best strength from the reviews, the number of reviews, and the number of likes from the users.
  • All the needed information except images i.e. introduction, the number of reviews for each strength, the number of total reviews, and the number of likes are contained in the response data of GET /cafes/:cafe_id/. Images are obtained using GET /cafe-imagse/?cafe_id.

/cafes/[cafe_id]/menu

  • RequireProfile
  • CagoButtonGroup
  • MenuContainer: Displays category name and the list of menu passed as props. Can delete each menu if editable flag is true, using DELETE /menus/:menu_id/.
  • GET /menus/?cafe_id API returns the list of menu with "category" field. Categorize the menu from data and display using MenuContainer for each category.

/cafes/[cafe_id]/reviews

  • RequireProfile
  • CagoButtonGroup
  • StatisticsContainer: In this page, displays the best strength, th number of reviews, and the average rating from the reviews.
  • ReviewCard: Displays a review. If the current user is the author of a review, then one can delete it by hitting the button on the review.
  • For each review from GET /reviews/?cafe_id, use ReviewCard to display its content.

/cafes/[cafe_id]/reviews/create

  • RequireProfile
  • RequireLogin
  • CreateReviewForm: User can select rating and strength ("Taste", "Service", "Mood") by hitting the corresponding buttons. After writing the content, the user can submit the review using POST /reviews/. Handles error on submission where the user is a manager or already have a review on the same cafe.

/cafes/[cafe_id]/board

  • RequireProfile

  • CagoButtonGroup

  • ArticleCard: Displays title and content of the article with the cafe"s name and avatar. Also displays comments of the article using CommentsList if the user hits the button. If editable flag is true, the user can edit or delete the article using PATCH/DELETE /board/:article_id/.

    • CommentsList: Used in ArticleCard and displays all the comments of the article. Each comment is displayed using CommentBox. The user can create a comment on the article using POST /comments/.
      • CommentBox: Displays the content of a comment with display name and avatar of the author. Used in CommentList. If the user is the author, one can edit or delete the comment using PATCH/DELETE /comments/:comment_id/.
  • Get the list of the articles of the cafe using GET /board/?cafe_id. For each article in the list, display it using ArticleCard then title and content of the article along with the comments will be displayed.

/admin/dashboard

  • RequireLogin
  • CafeSummary : Displays name, phone number, and address of the cafe. Also includes
  • CafeToggleSwitch which is a button that mutates the current cafe"s "force_closed" state.
  • "GET /cafes/?manager" is used here. For each cafe in the list, displays corresponding CafeSummary row-wise.

/admin/register-cafe

  • RequireLogin
  • KakaoMap
  • RegisterCafeForm : There are address, registration number, name, and phone number field. User can search cafes by the address. Using Kakao maps API"s geocoding and place search (by category), a list of cafes near the address is fetched and the center of the map is moved to the first cafe found. The black markers are displayed for the searched cafes. Initially a cafe is selected after a search, and user can select other cafes by clicking the markers. On select, the name and phone number fields are automatically filled. Submission is sent to POST /cafes/.

/admin/dashboard/[cafe_id]

  • RequireLogin
  • RequireManager: Renders children only if the user is a manager of the cafe, using query parameter i.e. [cafe_id] and GET /cafes/:cafe_id/. If it is confirmed that the logged in user is not a manager, redirect to "/admin/dashboard". Note that this component does not redirect if the user is not logged in, so RequireLogin should be used along.
  • Cafe images and introduction are fetched from GET /cafes/:cafe_id. Board articles, reviews, and menu are fetched respectively from GET /board/?cafe_id, GET /reviews/?cafe_id, and "GET /menus/?cafe_id. Information boxes are placed in grid, and the number of the columns are responsive to the screen.

/admin/dashboard/[cafe_id]/info

  • RequireLogin
  • RequireManager
  • ImageView
  • CafeIntroduction
  • StatisticsContainer
  • Similar to "/cafes/[cafe_id]/info" except that editable is true in CafeIntroduction.

/admin/dashboard/[cafe_id]/menu

  • RequireLogin
  • RequireManager
  • MenuContainer
  • CreateMenuForm: The user can create a menu with name, category, price, and is_main fields using POST /menu/.
  • editable is true in MenuContainer. There is a button to add a menu. If the button is clicked, a modal with CreateMenuForm inside is displayed.

/admin/dashboard/[cafe_id]/reviews

  • RequireLogin
  • RequireManager
  • StatisticsContainer
  • ReviewCard
  • Similar to "/cafes/[cafe_id]/reviews".

/admin/dashboard/[cafe_id]/board

  • RequireLogin
  • RequireManager
  • ArticleCard
  • editable is true in ArticleCard. Also there is a link to "/admin/dashboard/[cafe_id]/board/post".

/admin/dashboard/[cafe_id]/board/post

  • RequireLogin
  • RequireManager
  • PostArticleForm: User can fill title and content fields to post a new article using POST /board/. After submission, redirected to "/admin/dashboard/[cafe_id]/board"

/admin/dashboard/[cafe_id]/add-pictures

  • RequireLogin
  • RequireManager
  • ImageView
  • If there are one or more images, the user can set the current image as the main (representative) image of the cafe, using PATCH /cafe-images/:image_id/. Also one can upload a new image using POST /cafe-images/.

Database Schema

model

API List

Model Method Endpoint Description
User POST /auth/login/ Login
POST /auth/refresh/ Refresh Token
POST /auth/signup/ Sign up
GET /auth/logout/ Logout
CustomerProfile GET /customer-profile/me/ Retrieve my customer profile
POST /customer-profile/ Create customer profile
PUT/PATCH /customer-profile/:profile_id/ Update customer profile
Cafe GET /cafes/?location&?manager List cafes filtered by location or manager
GET /cafes/:cafe_id/ Retrieve cafe details
POST /cafes/ Create cafe
PUT/PATCH /cafes/:cafe_id/ Update cafe
CafeImage GET /cafe-images/?cafe_id List cafe images of cafe
POST /cafe-images/ Create cafe image
PUT/PATCH /cafe-images/:image_id/ Update cafe image
DELETE /cafe-images/:image_id/ Delete cafe image
Like POST /like/ Like cafe
DELETE /like/ Cancel liked cafe
CafeMenu GET /menus/?cafe_id List cafe menus
POST /menus/ Create cafe menu
PUT/PATCH /menus/:menu_id/ Update cafe menu
DELETE /menus/:menu_id/ Delete cafe menu
Review GET /reviews/?cafe_id List cafe reviews
POST /reviews/ Add cafe review
DELETE /reviews/:review_id/ Delete cafe review
BoardArticle GET /board/?cafe_id List cafe board articles
GET /board/:article_id/ Retrieve cafe board article
POST /board/ Post cafe board article
PUT/PATCH /board/:article_id/ Update cafe board article
DELETE /board/:article_id/ Delete cafe board article
BoardComment GET /comments/?article_id List comments on article
POST /comments/ Create comment
PUT/PATCH /comments/:comment_id/ Update comment
DELETE /comments/:comment_id/ Delete comment

API Details

If authorization is required for a request, a JWT access token should be placed in the authorization header in the following format: Authorization: Bearer <access_token>.

Cago API OpenAPI Specification 3.0

https://api.cago.fun/schema/swagger-ui/

Implementation Plan

Designing User Interface with Figma based on design diagrams will be also conducted. For each feature, corresponding pages, components, models, and APIs would be implemented together.

Subteams

  1. Choi Joonwoo and Park Jihyeong
  2. Jeon Hyeongmin and Oh Jinho

Plan Table

# Page Feature Difficulty Sprint Subteam Dependencies Done
1 /auth/login Sign in 4 3 1 - O
2 /auth/signup Signup 4 3 1 - O
3 /cafes/* Cago header 1 3 2 5 O
4 /admin/dashboard/* Cago admin header 1 3 2 - O
5 /create-profile Create customer profile 1 3 1 1, 2 O
6 /cafes Get cafes and each details on a map 4 4 1 - O
7 /admin/register-cafe Register cafe 4 4 1 1, 2, 6 O
8 /admin/dashboard Get managing cafes 2 4 2 1, 2, 6 O
9 /admin/dashboard/:id Get overall summary of a cafe 2 4 2 1, 2, 6 O
10 /cafes/:id/info, /admin/dashboard/:id/info Get/edit cafe information 2 5 2 1, 2, 6 O
11 /admin/dashboard/:id/add-pictures Add cafe images and choose a main image 3 5 1 1, 2, 6 O
12 /cafes/:id/menu, /admin/dashboard/:id/menu Get/add/delete cafe menu 2 5 2 1, 2, 6 O
13 /cafes/:id/review/*, /admin/dashboard/:id/review Get/add/delete cafe reviews 3 5 1 1, 2, 6 O
14 /cafes/:id/board, /admin/dashboard/:id/board/* Get/post/delete cafe articles and comments 2 5 2 1, 2, 6 O

Testing Plan

Unit Testing

Cago will use React Testing Library with Jest for Frontend testing, and unit test provided by Django Rest Framework for Backend testing. Each component or function would be tested with a corresponding test script, class, or function. For checking external dependencies, mocking would be used as main.

Functional Testing

Using React Testing Library and Jest to test whether it accepts the user stories, per page. All the implemented API on Django application is tested with Django Rest Framework unit testing class.

Integration Testing

Using Travis and Sonarcloud for continuous integration with static analysis. We are also considering to use Cucumber for end-to-end acceptance testing.