{"id":15770622,"url":"https://github.com/c-ehrlich/scheduler","last_synced_at":"2025-03-31T11:44:02.646Z","repository":{"id":134327144,"uuid":"362862174","full_name":"c-ehrlich/scheduler","owner":"c-ehrlich","description":"Final project for Harvard University CS50. Web app that lets users create events and register for time slots.","archived":false,"fork":false,"pushed_at":"2021-08-25T15:30:57.000Z","size":275,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-05T14:43:15.232Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/c-ehrlich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-29T15:24:23.000Z","updated_at":"2021-08-25T15:31:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"347c297d-f41f-486d-8002-339c633f9539","html_url":"https://github.com/c-ehrlich/scheduler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-ehrlich%2Fscheduler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-ehrlich%2Fscheduler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-ehrlich%2Fscheduler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-ehrlich%2Fscheduler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/c-ehrlich","download_url":"https://codeload.github.com/c-ehrlich/scheduler/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246465220,"owners_count":20781919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-04T14:43:23.784Z","updated_at":"2025-03-31T11:44:02.626Z","avatar_url":"https://github.com/c-ehrlich.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scheduler\n\n#### Description: Final project for Harvard University CS50. Web app that lets users create events and register for time slots.\n\n#### Video Demo: https://www.youtube.com/watch?v=cQ6SVQJTlwI\n\n![Scheduler Screenshot 1](https://i.imgur.com/Qxj2A83.jpg)\n\n![Scheduler Screenshots 2](https://i.imgur.com/4l9OAeN.jpg)\n\n## Requirements\n* cs50\n* Flask\n* Flask-Session\n* requests\n\n## Instructions (for demo usage)\n1. Duplicate scheduler.backup and rename the copy to scheduler.db\n2. In the root directory of the project, `flask run`\n\n## Notable Features and Design Decisions\n### UUIDs\nEach event is identified by a UUID, using a system that I build as I wanted different tradeoffs than Python's built-in UUID functionality. UUIDs are used both internally to identify events, and user-facing for telling people about events, emailing links, etc. Internally the system is not case sensitive, but the user-facing UUIDs are always all-caps. Each UUID consists of exactly eight upper-case letters - much shorter than the ones generated by Python's internal UUID function. My reasoning for this was:\n* Eight letters is a good length for a user-facing UUID as the length still allows for example transmitting for example by phone.\n* Having only capital letters lets the system avoid common mistakes such as I/l, O/0, etc.\n* 26^8 is about 200 billion - more than enough for UUIDs to be effectively impossible to guess or brute force.\n### User Accounts\nThere is only one type of user account. This means that any user can both host and attend events.\n### UI and other Front-End considerations\nI tried to keep the UI as simple as possible, thinking back to the early web apps as I find many current trends in web design to be actively user hostile. Here are a few examples of considerations I made during the design process:\n* High-contrast elements suggest the things the user will most commonly want to do\n* For actions that we really don't want users to accidentally do, such as deleting events, buttons turn red on hover, and lead to a modal where the confirm button once again turns red on hover.\n* Emphasis (for example the user's own name in a slot list) are achieved using simple html `\u003cstrong\u003e` tags\n* All front-end elements are designed so that user name fields support very long names - I checked all of them with the world's longest recorded human name.\n* The front-end is almost entirely built in HTML and CSS, with maybe 20 lines of JS. A stretch goal for a future version of this project is to build it entirely without JS.\n### Security \u0026 Data Integrity\n* The app adheres to Flask's Best Practices for avoiding SQL injection\n* Event hashes are guaranteed to be unique, and there are about 200 billion possible ones\n* Event hashes are non-sequential, ie not guessable\n* Backend security - the app is safe against injected JavaScript, bad requests, etc\n  * Users who are not the creator of an event cannot modify it\n  * Users cannot override other user's slots\n  * etc.\n* Event slots must end after they start and cannot overlap\n* No matter which order event slots are entered in, they appear correctly in all views\n* All data and time information is validated for formatting before being input into the database\n* And much more!\n\n## Limitations \u0026 Wish List\n### Deployment\n* The app currently only runs in test mode in Flask. Likewise the DB, while fully functional, is probably not ready for real-world deployment.\n### Accounts\n* A mail server (for account confirmation, notifications about event changes, etc)\n* Timezones (currently everything including the frontend runs in UTC)\n* Support for multiple people per slot, for group events\n* Safari on Mac prior to 14.1 (released April 2021) doesn't support \"data\" and \"time\" html input types properly, build a workaround for that\n* \"Garbage Bin\" - Events go somewhere before being fully deleted, to allow restoring accidentally deleted events\n* Transfer ownership of an event\n* Improved mobile/responsive layout\n\n## Database\n* The database is normalized to 3NF. \n### users\n```\nid INTEGER\nusername TEXT NOT NULL\nhash TEXT NOT NULL\nemail TEXT NOT NULL\nis_moderator INTEGER DEFAULT 0\nPRIMARY KEY (id)\n```\n### events\n```\nid INTEGER\neventname TEXT NOT NULL\ndescription TEXT NOT NULL DEFAULT \"\"\ndate STRING NOT NULL\nowner_id INTEGER\nhash TEXT NOT NULL\nPRIMARY KEY (id)\nFOREIGN KEY (owner_id) REFERENCES users (id)\n```\n#### slots\n```\nid INTEGER\ntime_start TEXT\ntime_end TEXT\nevent_id INTEGER NOT NULL\nuser_id INTEGER\nPRIMARY KEY (id)\nFOREIGN KEY (event_id) REFERENCES events (id)\nFOREIGN KEY (user_id) REFERENCES users (id)\n```\n\n## Files and notes\n### app.py\nThis contains most of the Model of the app. \n### helpers.py\nThe contains several helper functions\n* apology - This comes from CS50 Finance. Feed it an error code and it will display that error code alongside a cute cat\n* delete_event - This deletes an event and all associated slots\n* format_date - turnes a date such as \"2021-05-21\" into a more legible format such as \"21. May 2021\"\n* join_event - makes a user join an event, and removes them from any other slots they are occupying in the current event\n* leave_event - will remove a user from any slots they are attending in a given event\n* get_end_time - gets the end time of an event\n* get_start_time - gets the start time of an event\n* verify_slots - assures that all slots of an event don't overlap and don't finish before they start\n* week_day - returns the weekday (Monday, etc.) for a date with the date formating of the DB\n* login_required - this comes from CS50 Finance. Checks that the user is logged in before executing a route\n\n## Accounts and Events in sample DB\n### Accounts (Name, Email, Password)\n* David Malan david@cs50.io hunter2\n* Doug Lloyd doug@cs50.io hunter2\n* Brian Yu brian@cs50.io hunter2\n* Christopher Ehrlich christopher@cs50.io hunter2\n* Ernest and Berthold eandb@cs50.io hunter2\n* Loretta Spears loretta@cs50.io hunter2\n* Luc Tran luc@cs50.io hunter2\n* Conrad Squires conrad@cs50.io hunter2\n* Varun Dalby varun@cs50.io hunter2\n* Ellesha Mackenzie ellesha@cs50.io hunter2\n* Hettie Perez hettie@cs50.io hunter2\n* Yousuf Parks yousuf@cs50.io hunter2\n* Rikesh Jethanandani rikesh@cs50.io hunter2\n* Xiaoshi Zhang xiaoshi@cs50.io hunter2\n* Momoka Imamura momoka@cs50.io hunter2\n### Events (Name, Date, Hash)\n* CS50 Office Hours Week 3 - 26.4.2021 OISDRDTO\n* CS50 Office Hours Week 4 - 03.5.2021 JAZNNFVC\n* CS50 Office Hours Week 5 - 10.5.2021 SGWCDCZO\n* CS50 Office Hours Week 6 - 17.5.2021 FGBLQRTV\n* CS50 Office Hours Week 7 - 24.5.2021 OERGTPBI\n* Design Tutorial - Silhouette Project - 07.5.2021 JVCNQOWG\n* Midterm Presentation - Patternmaking 1 = 14.5.2021 GAYPYMBI\n* Japanese N3 - Oral Presentation - 16.5.2021 SVPKOPTR\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc-ehrlich%2Fscheduler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fc-ehrlich%2Fscheduler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc-ehrlich%2Fscheduler/lists"}