-
Notifications
You must be signed in to change notification settings - Fork 1
Design and Planning
- Rev. 1.0 2019-10-19 - initial version
- Rev. 2.0 2019-12-17 - revised
This picture shows the overall structure of triplannet system. Frontend is implemented using React and Redux, with Material UI. Backend is mainly implemented using Django. The client sends HTTP request to our service, and gets HTTP response back. The two main components communicate with each other using data in JSON format. Google Maps API is connected to our service in order to enable place searching service. We included Universarial Sentence Encoder model(from Tensorflow-hub) into our backend to encode sentences to word embedding vectors. Detailed explanation for each component will be provided in the following sections.
Here is ER diagram of our model design
This explains about ER diagram cardinality.
This ER diagram would implemented by django in our service. User and Travel can have many-to-many relation because we can have many collaborators for one schedule. So we add additional mapping table for collaborators to represent it. Similarly, we add Likes, View table for User and Travel many-to-many relation. We also add DL feature at travel table. For the recommendation purpose, we will store embedded vector for each travel plan by using Sentence2Vec model and calculate similarity when we recommend new travel plan. We also store distribution of block for the similar purpose We made nested design for the travel, travelCommit, travelDay, travelBlock to make a structure of travel. This design also make available to deal with a simple version control by travelCommit table, and modified field
-
Login page
(/login)- logging in with the user account
- Users can log in with other services’ account(Google, Facebook, …)
- If a user clicks ‘Sign up’ button -> moves to 2.
Sign up page
-
Sign Up page
(/sign_up)- Signing up a new user
- Duplicate check for ‘Email’ and ‘User Name’
- Password requirements will be applied (longer than N characters, …)
- If a user clicks ‘Cancel’ or ‘Confirm’ button -> moves to 1.
Login page
-
Header
- Header block will always be on the top of the page.
- If a user clicks reversed triangle of the header block -> Dropdown menu with ‘My Page’ and ‘Logout’ will be shown.
- If a user clicks ‘My Page’ in the dropdown menu -> moves to the user’s own 8.
User Info page
. - If a user clicks ‘Logout’ in the dropdown menu -> is logged out and moves to 1.
Login page
- If a user types in ‘@username’ -> list of users which include ‘username’ will be shown. If a user selects one of them -> moves to 8.
User Info page
of that user. - If a user types in ‘keyword’ -> list of ‘#tag’ which include ‘keyword’ will be shown. If a user selects one of them -> moves to 4.
Search page
with the search result of ‘#tag’
-
Main page
(/main)- Main page for users. Logged in users will be redirected here from 1.
Login page
- Shows several popular travel plans and recent plans. (default: 10 plans each)
- If a user clicks a travel plan block -> moves to 5.
Travel Detail page
of that travel plan.
- Main page for users. Logged in users will be redirected here from 1.
-
Search page
(/search)- Showing the search result of ‘#tag’.
- Only the search using a tag is supported.
- If a user clicks a travel plan block -> moves to 5.
Travel Detail page
of that travel plan.
-
Travel Detail page
(/travel/:id)- Showing the detail of the travel plan.
- If a user clicks ‘Fork’ button -> This plan will be copied to the user’s travel list in 8.
User Info page
, with the label of ‘Forked’. - If a user is viewing the plan of himself or herself, ‘Fork’ button is disabled.
- If a user clicks the profile picture or the name of the author -> moves to 8.
User Info page
of the author. - If a user clicks the triangle on the travel day block -> more detailed plans of the day are shown. These will disappear if the user clicks the triangle again.
- Related plans are provided using our recommendation algorithm using ML.
- A user can push ‘Like’ button.
- A user can add comments for the plan.
-
Create Travel page
(/travel/create)- Creating a new travel plan.
- A user can add a photo, a title, a summary, a description, and tags of a plan.
- If a user clicks ‘Select Period’ button in ‘Info’ tab -> Calendar modal pop-up will appear and a user selects the period of a travel there.
- Day blocks will be provided according to the selected periods. (ex 3 day blocks for 3-day-period)
- There are currently 5 kinds of travel blocks: Move, Food, Activity, Accomodation, Custom.
- A user can add plan block by drag-and-dropping travel blocks provided.
- A user can change the order of plan blocks by drag-and-dropping a travel block to desired position.
- A user can delete a plan block by drag-and-dropping it to the trash can icon.
- If a user finishes making a plan and clicks 'confirm', the plan is posted and the user is redirected to 5.
Travel Detail Page
.
-
Edit Travel page
(/travel/:id/edit)- Same as the create travel page, except that the existing plan will be loaded.
- If a user edits a travel plan, this will be stored as 'travel commit'. 'travel commit' will be merged into the origin plan when 'Merge' button is clicked.
-
User Info page
(/user/:id)- Showing the information of a specific user.
- If a user is viewing another user’s info page -> ‘Create a new plan’ button and ‘Edit’ button disappears.
- If a user clicks ‘Create a new plan’ button -> moves to 6.
Create Travel page
. - If a user clicks ‘Edit’ button -> moves to 9.
Edit User Info page
. - If a user clicks ‘...’ button on a travel block -> Dropdown menu with ‘Edit’, ‘Delete’, and ‘Logout’ will be shown.
- If a user clicks ‘Edit’ in the dropdown menu -> moves to 7.
Edit Travel page
of that plan. - If a user clicks ‘Delete’ in the dropdown menu -> The travel plan is deleted after alerting.
- If a user clicks ‘Settings’ in the dropdown menu -> moves to 9.
Travel Settings page
of that plan. - If the page is of now-logged-in user, plans to which the user is added as a collaborator is also shown.
- For plans on collaboration, 2 buttons are provided for dropdown menu when '...' button is clicked: 'Edit' and 'Quit'
- If a user clicks 'Quit' in the dropdown menu of a plan on collaboration -> The user will be removed from the collaborators list of the plan, and the plan will not show on the user's page.
- For plans that are not the head of a travel, 'Merge' button will be also shown in the dropdown menu.
- If a user clicks 'Merge' after some editing, the edited content will be applied to the origin travel.
-
Edit User Info page
(/user/:id/edit)- Editing the information of a user.
- If a user clicks ‘Change’ button -> Related input fields, ‘Cancel’ button, and ‘Confirm’ button will appear.
- User can change his/her password, nickname, and status message here. Each section has own 'Confirm' button, and this will apply changes for each item.
-
Travel Settings page
(/travel/:id/settings)- Manage collaborators and editing the settings of a travel plan.
- If a user clicks ‘Add’ button -> Input field for username will appear. The behavior of the input field is the same as the search field of the header when searching a user.
- Radio buttons for setting ‘Visibility’ and ‘Comments’ is provided.
-
Login
-
username
- User id that a user entered.
-
password
- User password that a user entered.
-
onSubmit()
- Request login to backend, get user hash key
- If a user succeed to login, this page will be redirected to recent schedule page.
- If a user fail to login, the reason of login failure will be spanned below the password input tag.
-
-
Sign Up
-
email
- User id that a user entered, this value always be checked to be email format.
-
password
- User password that a user entered.
-
password_confirm
- Password confirm that a user entered. This value is expected to be same with
password
. The confirmation is checked automatically withonChange
- Password confirm that a user entered. This value is expected to be same with
-
nickname
- User nickname that a user entered.
-
is_confirm_failure
- Boolean value
- If the password and password confirm value are not same, this value will be true o.w. false.
-
checkEmail()
,checkNickname()
- The email/nickname that user entered must be identical under the database.
- When a user click
check
button next to the username input tag, this handler will requestcheckEmail
,checkNickname
. - If the claimed username is already in the database, the value of the username input tag would be
null
and alert. - If the claimed username is not in the database, the
check
button isdisabled
until the user change the username value.
-
signUpButtonHandler()
- Request new user information to backend, get user hash key
- Redirect to login page when signUp is succeeded.
-
cancelButton Handler()
- Redirect to Login page.
-
-
My Travel
-
travelSchedules
-
this.state.travelSchedules
keeps save all schedules registered the user. - All contents should contain a title, a period, number of likes, description, image link, is_forked.
-
-
clickScheduleDetailHandler()
- This method will be called when a user click a travel block.
- Move to travel detail page.
-
clickEditScheduleHandler()
- This method will be called when a user clicks
Edit Button
. - Move to edit travel schedule page.
- This method will be called when a user clicks
-
clickDeleteScheduleHandler()
- This method will be called when a user clicks
Delete Button
. - Delete the schedule after
window.confirm
the action.
- This method will be called when a user clicks
-
clickScheduleSettingHandler()
- This method will be called when a user clicks
Setting Button
. - Move to travel setting page.
- This method will be called when a user clicks
-
clickCreateScheduleHandler()
- This method will be called when a user clicks
Create Button
. - Move to create travel page.
- This method will be called when a user clicks
-
-
User Travel
-
travelSchedules
-
this.state.travelSchedules
keeps save all schedules registered the user. - All contents should contain a title, a period, number of likes, description, image link.
-
-
clickScheduleDetailHandler()
- This method will be called when a user click a travel block.
- Move to travel detail page.
-
-
Create Travel
-
Title
,Summary
,Description
- Text data that a user writes
-
Image
- A user can add his/her image about the travel.
-
StartDate
- Start datetime contains year, month, day
-
EndDate
- End datetime contains year, month, day
-
Tags
- Several tags started with '#'
-
Travel Blocks
- All travel block data, title, description, period ...
-
clickSubmitHandler()
- This method will be called when a user clicks
Submit button
. - Create a new travel schedule and redirect to travel detail page.
- This method will be called when a user clicks
-
-
Edit Travel
- same as
Create Schedule
page, but initial state value would be travel information.
- same as
-
Travel Detail
-
Title
,Summary
,Description
- Text data that a user writes
-
Image
- Image that users added
-
Period
- Travel period that contains year, month, day
-
Tags
- Several tags started with '#'
-
Travel Blocks
- All travel block data, title, description, period ...
-
Recommendation Travels
- All travels have their recommendation travels.
- Communicate with backend to show the recommendations.
-
Comments
- All comments related to a travel schedule
-
newComment
- A comment that a user writes
-
Likes
- Integer value of
likes
numbers
- Integer value of
-
commentHandler()
- This method will be called when a user clicks
Comment button
. - Create a new comment to travel detail page.
- This method will be called when a user clicks
-
clickLikeHandler()
- This method will be called when a user clicks
LIKE
. - The likes number of the travel will be added.
- This method will be called when a user clicks
-
clickForkHandler()
- This method will be called when a user clicks
Fork button
. - The travel schedule will be cloned to a user space.
- This method will be called when a user clicks
-
clickScheduleHandler()
- This method will be called when a user click
Travel Block
. - Redirect to some recommended travel detail page.
- This method will be called when a user click
-
-
Travel Setting
-
collaborators
- The list of collaborators of the travel schedule.
-
authorization
-
Private
orPublic
-
-
allowComment
- T/F
-
clickSubmitHandler()
- This method will be called when a user clicks
Submit Button
. - Submit changed the settings of the schedule.
- This method will be called when a user clicks
-
searchCollaborator(string)
- This method will be called when a user clicks
Search Button
. - The recommended username will be served.
- This method will be called when a user clicks
-
-
Header
-
clickIconHandler()
- This method will be called when a user clicks
Icon
. - Redirect to Recent Schedule page.
- This method will be called when a user clicks
-
clickMyPage()
- This method will be called when a user clicks
MyPage
button. - Redirect to My Travel page.
- This method will be called when a user clicks
-
logoutHandler()
- This method will be called when a user clicks
Logout Button
. - Break the session and redirect to login page.
- This method will be called when a user clicks
-
-
Search Tab
-
query
- Search query
-
onChangeHandler()
- This method will be called when a user writes some queries.
- Matching username or tags will be expanded under the query.
-
clickSearchHandler()
- This method will be called when a user clicks
Search Button
. - Show the results of query with
Search Schedule
page.
- This method will be called when a user clicks
-
-
Recent Travel
-
popularTravel
,recentTravel
- Travel Schedule lists.
-
clickScheduleDetailHandler()
- This method will be called when a user clicks a travel block.
- Move to travel detail page.
-
-
Search Travel
- Same as
Recent Schedule
with specific data
- Same as
-
User Profile
-
thumbnail
,status
- Custom image, status that represent the user.
-
password
,password confirm
- Password information to be edited.
-
handleProfile()
- To handle image that user handles
-
clickSubmitHandler()
- This method will be called when a user clicks
Submit Button
. - Submit changed the user profile.
- This method will be called when a user clicks
-
-
400, 404, 500 Error Page
-
clickLoginHandler()
- This method will be called when a user clicks
Login Button
. - Redirect to Login page.
- This method will be called when a user clicks
-
-
TravelOverviewBlock
-
clickTravelHandler()
- Redirect to travel detail page.
-
clickEditScheduleHandler()
- This method will be called when a user clicks
Edit Button
. - Move to edit travel schedule page.
- This method will be called when a user clicks
-
clickDeleteScheduleHandler()
- This method will be called when a user clicks
Delete Button
. - Delete the schedule after
window.confirm
the action.
- This method will be called when a user clicks
-
clickScheduleSettingHandler()
- This method will be called when a user clicks
Setting Button
. - Move to travel setting page.
- This method will be called when a user clicks
-
-
TravelHeaderBlockView, TravelHeaderBlockEdit
-
clickSubmitHandler()
- This method will be called when a user clicks
Submit Button
. - Submit changed items.
- This method will be called when a user clicks
-
-
TravelDayBlockView, TravelDayBlockEdit
-
clickSubmitHandler()
- This method will be called when a user clicks
Submit Button
. - Submit changed items.
- This method will be called when a user clicks
-
clickSpreadHandler()
- This method will be called when a user clicks
Spread Button
(shape of inverted traingle). - show or hide the all units of this travel day block.
- This method will be called when a user clicks
-
-
TravelUnitBlockView, TravelUnitBlockEdit
-
clickSubmitHandler()
- This method will be called when a user clicks
Submit Button
. - Submit changed items.
- This method will be called when a user clicks
-
clickSearchHandler()
- This method will be called when a user clicks
Search Button
. - Return recommended places list(through Google Maps API)
- This method will be called when a user clicks
-
clickCalenderHandler()
- This method will be called when a user clicks a time period window.
- Show the calendar window to select the period of the unit.
-
clickTravelIconHandler()
- This method will be called when a user clicks
Icon
. - Span the Icon block to choose representatative icon of the unit.
- This method will be called when a user clicks
-
-
UserProfile
-
clickEditHandler()
- This method will be called when a user clicks
Edit Button
. - Redirect to User Profile page.
- This method will be called when a user clicks
-
- User
-
getUser()
- get a user profile like status, thumbnail, etc.
-
login()
- post login to server with given username and password.
-
logout()
- logout the currently logged in user.
-
signUp()
- post a new user to backend with username, password, nickname.
-
isLoggedIn()
- request the logged in session is valid.
-
setUserSessionStorage()
- store the user at user's sessionStorage.
-
getUserSessionStorage()
- get the stored user from sessionStorage.
-
setUserProfile()
- request the edited profile of user.
-
setUserPassword()
- request the changed password of user.
-
searchUser()
- request recommended user list given user string.
-
- Travel
-
getTravel()
- get each travel information
-
setTravel()
- set edited travel information.
-
deleteTravel()
- delete specific travel.
-
getRecentTravel()
- get recent travel list to show recent travel page.
-
getPopularTravel()
- get popular travel list that sorted with likes to show recent travel page.
-
searchTravel()
- search travel query and get
popular travel
andrecent travel
.
- search travel query and get
-
getUserTravel()
- get some travels that the user registered.
-
forkTravel()
- clone the travel to the user.
-
mergeTravel()
- merge the travel with origin travel.
-
getRecommendTravel()
- request recommended travel with given travel(machine learning feature).
-
likeToggle()
- change like status.
-
- Place
-
getPlace()
- get each place information.
-
postTag()
- cache information that place searched.
-
searchPlace()
- request autocomplete place list given place query.
-
- Comment
-
getComments()
- request all comments related to the travel.
-
postComment()
- post a new comment.
-
deleteComment()
- delete my comment.
-
editComment()
- edit my comment.
-
- Above halven picture is about frontend relations.
- Dotted lines are container relations.
- Solid lines are relations between containers and others.
The data exchange between the frontend and the backend using the HTTP protocol consists of the following restful APIs.
API | GET | POST | PUT | DELETE |
---|---|---|---|---|
user/auth/ | X | login | X | X |
user/signup/ | X | Create new user | X | X |
user/:id/ | Get specified user | X | Edit specified user information | X |
user/:id/profile_photo/ | X | X | Change user's profile photo | X |
user/serach/:query/ | Search user by email | X | X | X |
user/check/email/:email/ | Check duplicate email | X | X | X |
user/check/nickname/:nickname/ | Check duplicate nickname | X | X | X |
user/search_by_nickname/:query/ | Search user nickname | X | X | X |
API | GET | POST | PUT | DELETE |
---|---|---|---|---|
travel/ | X | Create new travel | X | X |
travel/:id/ | Get specified travel by request user | X | X | Delete specified travel |
travel/:id/fork/ | X | Fork specified travel and create new travel | X | X |
travel/:id/travelCommit/ | X | Create new travelCommit under specified travel | X | X |
travel/:id/comment/ | Get comment list of specified travel | Create new comment on specified travel | X | X |
travel/:tid/comment/:cid/ | X | X | Update specified comment | Delete specified comment |
travel/travelCommit/:id/photo/ | X | X | Change the photo of specified travel commit | X |
travel/travelCommit/:id/merge/ | X | Merge specified travel commit into travel | X | X |
travel/recent/ | Get most recent travel list | X | X | X |
travel/popular/ | Get most popular travel list | X | X | X |
travel/search/:query/ | Get travel list that contain specified tag | X | X | X |
travel/user/:id/ | Get travel list written by specified user | X | X | X |
travel/collaborator/:id/ | Get travel list that specified user collaborating | X | X | X |
travel/tag/:tag/ | Get tag list that contains specified tag | Create new tag | X | X |
travel/recommend/:id/ | Get similar recommendation travels by specified travel | X | X | X |
travel/recommend/:uid/:tid/ | Get similar recommendation travels by user and travel | X | X | X |
travel/settings/:id/ | X | X | Change settings of specified travel such as collaborators | X |
travel/view/:id/ | X | Update specified travel's viewer list | X | X |
travel/like/:id/ | X | Update specified travel's like list | X | X |
API | GET | POST | PUT | DELETE |
---|---|---|---|---|
maps/autocomplete/:query/ | Get autocomplete query and save it as cache | X | X | X |
maps/search/:query/ | Get search result of Google maps API and save result in cache | X | X | X |
The service will deploy through two servers: backend, frontend. Each server should set https ssl to garantee secure communication between server and client. Our backend consist of django library and the database would be mounted on MySQL engine. The backend server always handle database with the engine and communicate with django models. The server also response several requests asynchronously, nginx will be applied to server to handle the requests. If the requests would be expected hard with auto-complete search tab function, we can apply gunicon to the backend server to handle this.
The application could serve recommendation system within the travel detail page. The pretrained sentence2vec model should always mounted backend server, this might be disadvantages to the server. The server should be managed carefully with memory management tools like supervisord, etc.
When a user create travel data, the place data should be served to the user, and this should be implemented by google maps API.
The purpose of our service is to share my travel plan and manage some detail travel plan with web application. For this purpose the Create Travel
page and Travel Detail
page are the key feature of the service. Behind frontend components and relations Create Travel
page and Travel Detail
page contains lots of components and backend details. We separate these page into small component to implement step by step. Each page and backend model has its own test module, so try to remove dependency while implement service.
Some frontend components are quite similar, for example My Travel
page and User Travel
page have same format. We make the common part of these container to one component and try to implement this component early. The first schedule of frontend is to implement Create Travel
and Travel Detail
page. The second schedule of frontend is to implement Search
page, this feature will be challenging because the length of travel plans will be chagned dynamically.
It is easy to implement frontend components after implement related backend models. All backend models should be implemented earlier than other services, and the model should remain unchanged until the project is over. When the model is fixed, the API will be implemented with reducers in frontend components. After that, the testings for both frontend and backend will be followed to ensure the frontend and backend work properly
Every members will challenge to implement both backend and frontend. All issues and communication should share with issue page and PR page. Below table is feature and assignee of the service.
Page | Feature | Time | Sprint | Assignee | Challenge |
---|---|---|---|---|---|
Login | Handle user session | 1d | 2 | Suh | |
Sign Up | check user input valid | 1d | 3 | Han | |
My Travel | list all my travels | 2d | 3 | Hwang | |
User Travel | list all use travels | 0.5d | 3 | Jang | |
Create Travel | add travel component | 7d | 3,4 | Hwang | Drag & Drop component, Hard test cases |
Edit Travel | edit travel plan | 1d | 3,4 | Jang | |
Travel Detail | Overview travel, comment | 3d | 3,4 | Suh | handle likes, comments |
Search | map user and travel within query | 3d | 4,5 | Han | Test execution time |
Header | common page | 1d | 3 | Hwang | |
User Profile | change user info | 1d | 4 | Jang | |
Travel Setting | change travel setting | 1d | 4 | Jang | |
Error Page | 400, 500 errors | 1d | 5 | Suh |
Model | Feature | Time | Sprint | Assignee | Challenge |
---|---|---|---|---|---|
User | handle login | 2d | 3 | Jang | |
Travel | travel information | 3d | 3 | Han | |
Comment | comment on travel | 2d | 3 | Suh | |
place | POI data | 2d | 3 | Hwang |
Service | Feature | Time | Sprint | Assignee | Challenge |
---|---|---|---|---|---|
Search | select travel matching query | 4d | 4,5 | Han | The most time consuming feature |
ML feature | sentence2vector | 6d | 4,5 | Jang | Would inference model be fast? Add ml model metric |
Google Maps API | connect the service and google API | 3d | 3,4 | Hwang |
Page | Feature | Time | Sprint | Assignee | Challenge |
---|---|---|---|---|---|
Login Test | Handle user session | 1d | 3 | Suh | |
Sign Up Test | check user input valid | 1d | 3 | Han | |
My Travel Test | list all my travels | 1d | 3 | Hwang | |
User Travel Test | list all use travels | 0.5d | 3 | Jang | |
Create Travel Test | add travel component | 2d | 4 | Hwang | Drag & Drop component, Hard test cases |
Edit Travel Test | edit travel plan | 1d | 4 | Jang | |
Travel Detail Test | Overview travel, comment | 1d | 4 | Suh | handle likes, comments |
Search Test | map user and travel within query | 1d | 5 | Han | Test execution time |
Header Test | common page | 1d | 3 | Hwang | |
User Profile Test | change user info | 1d | 4 | Jang | |
Travel Setting Test | change travel settint | 1d | 4 | Jang | |
Error Page Test | 400, 500 errors | 1d | 5 | Suh |
Model | Feature | Time | Sprint | Assignee | Challenge |
---|---|---|---|---|---|
User Test | handle login | 1d | 3 | Jang | |
Travel Test | travel information | 1d | 3 | Han | |
Comment Test | comment on travel | 1d | 3 | Suh | |
place Test | POI data | 1d | 3 | Hwang |
We need to test for both frontend and backend. All components and modules need to be tested. For the frontend, we use React and Redux, so we will use Jest and Enzyme for framework. We will use Mock and Spy for components with externel depedency. For the backend, we use Django, so we will use Django’s TestCase class which is based on Python unittest.
We will test all RESTful APIs. Test will check wheter APIs give appropriate response, or do appropriate action. Also we will test the functions are well working by checking the results or responses for the components For the frontend, we will use Jest and Enzyme for testing APIs used by React and Redux. For the backend, we will use Django’s TestCase class which is based on Python unittest.
For the accpetance test, we have to check whether desired changes are maded when some event occurs. We will use Jest and Enzyme for the testing. For the integration test, we will use Travis CI.
Our goal is to achieve above 90% of test coverage, with appropriate tests.