Skip to content

Repository files navigation

GitHub commit activity GitHub last commit GitHub repo size

A Comprehensive Watch Collection Management Tool

Watch-O-Tron is a versatile tool designed to efficiently manage your watch collection. It enables you to track all your watches, including detailed information such as make, model, and brand collection. Additionally, movement details can be stored including type and calibre/module information. For watches with intricate complications, these can be noted and highlighted with user-friendly icons. An image can also be uploaded for each watch.

While it is recommended to have all watch details readily available, the only essential information required to store a watch is it's make and movement type.

Watch-O-Tron offers the flexibility to edit watch details at your convenience. You can also delete watches and transfer them between different lists.

As watch enthusiasts often acquire new watches, Watch-O-Tron provides a convenient feature to add watches to a wish list for desired watches. Upon making a purchase, you can effortlessly transfer the watch to your collection by using the purchased action button.

Staff members also have access to the staff settings area, which grants them the ability to add, edit, and remove custom movements and list types. However, default movements and lists cannot be modified.

screenshot

Template source: mockupworld

UX

Strategy

Create a feature-rich web app for watch enthusiasts which enables them to manage and track their collections.

Scope

Features I wanted to include were:

  • Separate accounts for every user so their collection remains private.
  • The ability for a user to add watches to the app with accompanying details.
  • Have a collection and wish list section to enable grouping of watches.
  • The ability to edit and delete watches.
  • Be able to move watches from a wish list to a collection in a simple step.
  • Have a staff-level user which gives them access to a settings page to add, edit, and remove custom movements and lists.
  • Some Easter eggs for users to find.

Structure

The site would be based around a main home page that displays a user's watches. Mobile users will navigate the site via a pop-up menu situated at the bottom of the screen for easier access. When viewed on larger screens, the navigation will move to the top. Available lists will be clickable with the current list being highlighted. When a user selects a new list, the page will update and display the watches in the newly selected list. The default lists are "Collection" and 'Wish List", these will always be available to view. Any other lists created by staff will only be available to view if the user has added watches to them.

The button to add a watch will be easily accessible via the menu on mobile devices and at the bottom of the screen for larger devices. Adding and editing a watch will present a new page to the user specifically for data input. When they submit the new watch info, it is presented back to them for confirmation before being added to a chosen list.

The user will also have confirmation of their login displayed along with a button to log out.

If the user is a staff member or a super user, they will be informed and also have extra navigation options. Staff members will have access to the staff settings page, and super users will have access to the staff settings and additionally the Django admin panel for the site.

The staff settings page will have tables to show the current movements and lists available for users. Staff members can add, edit, and delete any new movements or lists created. The default lists "Collection" and "Wish List" cannot be changed or deleted. Also, the default movement types cannot be changed or deleted. The staff settings page enables a client to update the app in response to users’ requests.

Skeleton

In the wireframing process, I decided the navigation should be simple and remain constant throughout the site where possible. Having navigation on the bottom for mobile devices makes it easier for the user to interact with while keeping the screen visible. The navigation would move to the top for larger screens for a more traditional layout. Clicking on a watch will present you with the action buttons for each watch. An edit logo on the image and cursor change will indicate that this can be done.

Colour Scheme

Because watches come in a multitude of colours and patterns, I decided to go with a neutral monochrome scheme for the site, with only the action buttons and main logo having colour. This in turn creates a personal colour scheme for each user, as the images of the watches they upload will influence the colour scheme of the site.

For the action buttons, I used the Bootstrap 5 standard colour schemes, trying to keep each colour to a specific type of action. This would lead the user naturally to each button when presented, depending on what they wanted to do.

Colour Ref Site Elements
rgb(220, 220, 220) Main site background
#FFF Navigation background
rgb(240, 240, 240) Mobile nav item backgrounds
rgb(220, 220, 220) Mobile active nav item background
rgb(220, 220, 220) Edit modal background
rgb(240, 240, 240) Login / Logout / Signup content background
rgb(240, 240, 240) Staff settings content background
#CC0000 Main logo clock hands
Colour Ref Buttons Action Type
bootstrap danger Sign Out / Delete buttons Destructive
bootstrap success Sign In / Add a Watch / Add / Confirm / Amend buttons Constructive
bootstrap primary Sign Up / Staff Settings / Purchased / Cancel buttons Progress
bootstrap warning Edit buttons Alteration
bootstrap secondary Admin Panel button Admin

Typography

Complication Icons

Some icons from Font Awesome were used and some were created by myself.

Complication Source
Chronograph Font Awesome
Day Custom
Date Custom
GMT Font Awesome
World Timer Font Awesome
Moonphase Custom
Power Reserve Custom
Tourbillon Custom

User Stories

New Site Users

  • As a new site user, I can sign up for an account so that I can log in and use the app.

Returning Site Users

  • As a site user, I can log in so that I can use the app.
  • As a site user, I can log out so that I can keep my data private.
  • As a site user, I can reset my password with an email link so that I can regain access to my account if I forgot the password without having to contact admin.
  • As a site user, I am notified on successful login and logout so that I know that I am logged in or out.
  • As a site user, I can view my watch collection so that I can view images and details of the watches I own.
  • As a site user, I can view my wish list so that I can see what watches I want or plan my next purchase.
  • As a site user, I can view watches that I have placed in potentially added new list types so that I can see the watch details for this list.
  • As a site user, I can see the details of each watch so that I can find out more information about them.
  • As a site user, I am notified when I have switched views to a new list so that I know which list I am viewing.
  • As a site user, I can add a new watch so that I ca see it in my collection or wish list.
  • As a site user, I am asked to confirm new watch details I entered are correct so that no accidental erroneous data is saved.
  • As a site user, I am notified when a watch has been added successfully so that I know the addition was successful or not.
  • As a site user, I can see a spinner when I click add watch so that I know something is happening.
  • As a site user, I should be prompted to confirm watch deletions so that I do not delete watches by accident.
  • As a site user, I can edit stored watches in my collection so that I can add more detail or update existing information.
  • As a site user, I can move a watch in my wish list to my collection so that I know that I have purchased it.
  • As a site user, I can delete a watch from the wish list so that I can update my wish list should I no longer want a particular watch.
  • As a site user, I can delete a watch from a new list type so that I can update this list when I no longer want the watch to appear in it.
  • As a site user, I can edit stored watches in my wish list so that I can add more detail or update existing information.
  • As a site user, I can edit stored watches in a new list type so that I can add more detail or update existing information.
  • As a site user, I can delete a watch from my collection so that I can update my lists if I no longer own a particular watch.
  • As a site user, I should be prompted to confirm alterations so that edits are correct.
  • As a site user, I should be asked to confirm when I set a watch as purchased so that I don't accidentally move a watch to my collection if I haven't bought it.
  • As a site user, I am notified after editing and deleting watches so that I know if the process was successful.
  • As a site user, I am notified when I move a watch to the collection so that it is confirmed whether the process was successful.
  • As a site user, I can see a spinner when I confirm a watch edit so that I know something is happening.
  • As a curious site user, I can discover a hidden Easter egg in the site logo so that I experience an unexpected, delightful surprise within the application.
  • As a curious site user, I can discover a hidden Easter egg in the date complication icon so that I experience an unexpected, delightful surprise within the application.
  • As a curious site user, I can discover a hidden Easter egg in the day complication icon so that I experience an unexpected, delightful surprise within the application.
  • As a curious site user, I can discover a hidden Easter egg in the moon phase complication icon so that I experience an unexpected, delightful surprise within the application.
  • As a site user, I can post in a forum and comment on posts so that I can connect with other like-minded users.
  • As a site user, I can send direct messages to other users so that I can have private conversations with other users.
  • As a site user, I can delete my account so that the app no longer stores any of my information.

Staff Member

  • As a client, I can log in as a staff member so that I can add potential new, important options for users.
  • As a site staff member, I can add new watch movement types to the model so that users can add watches with any new movement types that may become available in the future.
  • As a site staff member, I can add new list types so that users can expand their lists from collection and wish list to other types specified by the site staff member.
  • As a site staff member, I can edit any movement types I have added so that I can change them if needed.
  • As a site staff member, I can delete any new movement types so that I can keep the list relevant.
  • As a site staff member, I can edit any added list types so that I keep the app up to date.
  • As a site staff member, I can delete custom added lists so that I can remove any unwanted list types.
  • As a staff member, I am notified about edits and deletes I make for custom movements so that I know if the change was successful.
  • As a staff member, I am notified of successful list edits and deletions so that I know the process was successful.

Site Admin

  • As a site admin, I can log in as a super user so that I can access the admin panel.

Wireframes

To follow best practice, wireframes were developed for mobile, tablet, and desktop sizes. I've used Balsamiq to design my site wireframes.

Mobile Wireframes

Log In / Register Homepage Homepage Showing Detail Homepage Expanded Menu Wish List Showing Detail Add/Edit Add/Edit Expanded Menu Add/Edit Confirmation Staff Member Homepage Expanded Menu Staff Member Add/Edit Staff Member Add/Edit Expanded Menu
wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe

Tablet Wireframes

Log In / Register Homepage Homepage Showing Detail Homepage Expanded Menu Wish List Showing Detail Add/Edit Add/Edit Expanded Menu Add/Edit Confirmation Staff Member Homepage Expanded Menu Staff Member Add/Edit Staff Member Add/Edit Expanded Menu
wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe

Desktop Wireframes

Log In / Register Homepage Homepage Showing Detail Homepage Expanded Menu Wish List Showing Detail Add/Edit Add/Edit Expanded Menu Add/Edit Confirmation Staff Member Homepage Expanded Menu Staff Member Add/Edit Staff Member Add/Edit Expanded Menu
wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe wireframe

Features

Existing Features

  • Title and Logo

    The title and logo remain in the same place throughout the site. Curious users may notice it is not always the same...

    screenshot

  • User Accounts

    Individual Accounts

    • When you first navigate to the Watch-O-Tron, you are required to log in or create an account. This is because every user needs their own account to use the site. This keeps their information private and stops anyone without authorisation from editing their data. When logged in, your username is displayed so that you know you are logged in to the correct account. Every page also has the log-out button.

    Sign In Sign Up Sign Out
    screenshot screenshot screenshot
    Sign Out Button Mobile Sign Out Button Desktop
    screenshot screenshot
    • If a user has entered an email during signup they can use the forgot password link on the login page to request an email to reset their password.
    Password reset request mobile Password reset request desktop
    screenshot screenshot

    Different Account Levels

    • There are three levels of user, each with different levels of access:
      • User: this is the default level with the following privileges:

        • Access their account.
        • View their watches.
        • Add a watch to any available list.
        • Edit any of their watches.
        • Delete any of their watches.
      • Staff Member: this is the standard level that would be given to a client user. They have all the same privileges as User with the additions:

        • Access to the staff settings page.
        • Add a new custom movement type and list.
        • Edit any custom movements or lists.
        • Delete any custom movements or lists.

        Note: staff members cannot edit or delete the default types of movement or list.

      • Super User: this is the highest level and only for site administrators. In addition to User and Staff Member privileges, they can:

        • Access the Django Admin Panel.
        • Create any type of user.
        • Edit any user.
        • Delete any user.
        • Create new default movements or lists.
        • Edit any movement or list.
        • Delete any movement or list.

    If you are a staff member or super user (admin), it will be displayed next to your username, and you will be presented with extra buttons to access the appropriate settings given to you.

    User Staff Member Super User
    Mobile screenshot screenshot screenshot
    Desktop screenshot screenshot screenshot
  • Site Navigation

    Note: Tapping/clicking on the main logo will bring you back to the home page on both mobile and desktop versions.

    Mobile

    Most navigation of the site on a mobile device is done through the collapsing navbar at the bottom of the screen. From here, you can:

    • View all the lists you currently have watches stored in.
    • Add a new watch.
    • Log out.
    • Access any user-level-specific pages.

    If the current list of watches you are viewing contains more than 8 watches, you will get a pagination navigation bar appear just above the menu.

    Mobile Navbar Mobile Navbar Expanded Mobile Pagination
    screenshot screenshot screenshot

    Desktop

    The main navigation for desktop devices is located at the top of the screen. From here, you can:

    • View all the lists you currently have watched stored in. Collection and Wish List are always visible. Any extra custom lists are shown in the dropdown menu.
    • Log out.
    • Access any user-level-specific pages.

    To add a watch, the button is located at the bottom of the screen in a prominent central position. If the current list of watches you are viewing contains more than 8 watches, you will get a pagination navigation bar appear just above this button.

    Desktop Navbar Desktop Navbar Expanded Desktop Add Watch Desktop Pagination
    screenshot screenshot screenshot screenshot
  • Viewing Watches

    The main page in Watch-O-Tron is where you can see your watches. When you first visit the site, the default view is your Collection. You can then navigate to different lists to see all your watches in each list. If a list contains more than 8 watches, the view will be paginated to maintain good site performance.

    If a list is empty, you will be notified and prompted to add a watch.

    Viewing on mobile Viewing on tablet Viewing on desktop
    screenshot screenshot screenshot
    Empty list mobile Empty list tablet Empty list desktop
    screenshot screenshot screenshot
    • Typical Watch Display

      Each watch has its own card which displays the information added by the user. An image is the main focus of each card with the particular watch details underneath (if no image is provided, a placeholder is used). Complications are shown as icons with them in prominent black if the watch has it and a faded grey if not. A curious user may notice something about some of these icons...

      Typical watch with uploaded image Typical watch with placeholder
      screenshot screenshot
    • Tooltips

      The watch displays use icons to depict the complications that each watch has. For new users, this may be a little confusing as to what each one is. Therefore, tooltips appear for each one.

      Complication Tooltip
      Chronograph screenshot
      Day screenshot
      Date screenshot
      GMT screenshot
      World Timer screenshot
      Moonphase screenshot
      Power Reserve screenshot
      Tourbillon screenshot
  • Adding Watches

    When you click on the Add Watch button, you are presented with a form to fill out with the following details about the watch:

    • Make (required)
    • Collection
    • Model
    • Movement type (required, selectable from dropdown)
    • Movement model
    • List name (required, selectable from dropdown)
    • Image (placeholder image used if none uploaded)

    Then you can select which of the following most common watch complications it has (if any):

    • Chronograph
    • Day
    • Date
    • GMT
    • World Timer
    • Moonphase
    • Power Reserve
    • Tourbillon

    Only the Make, Movement Type, and user list are required when entering a watch. You can add more later if required. If you decide you no longer wish to add this watch, you can click on cancel to return to the list you were viewing.

    Watch input mobile Watch input tablet Watch input desktop
    screenshot screenshot screenshot

    Once you have entered the info and clicked on Add Watch, you are presented with the details for confirmation, including any image uploaded. If no image was chosen, a placeholder is used.

    Watch confirmation mobile Watch confirmation tablet Watch confirmation desktop
    screenshot screenshot screenshot
    Watch placeholder mobile Watch placeholder tablet Watch placeholder desktop
    screenshot screenshot screenshot

    When you have confirmed the details are correct, the watch is added to the chosen list and you are redirected to that list. If you notice a mistake, you can click on edit to return to the input form where you can make changes. Also, if you decide that you no longer wish to add this watch at the confirmation stage, you can click on cancel to return to the list you were previously viewing.

    To prevent accidental loss of watch info, the user will be prompted if they attempt to navigate away from the page using any links while in the add watch form. They can then decide to continue adding/editing or leave.

    Navigating away prompt mobile Navigating away prompt tablet Navigating away prompt desktop
    screenshot screenshot screenshot
  • Watch Action Buttons

    Each watch has its own action buttons which allow the user to manage each watch individually. To access these buttons, they simply click anywhere on the watch they wish to update. There are two default action buttons which are 'Edit' and 'Delete'. If the watch is located in the Wish List, then there is an extra action button labelled 'Purchased' that they can use to quickly move the watch to the Collection without going into the edit function.

    Standard action buttons Wish List action buttons
    screenshot screenshot
  • Purchased Watches

    When viewing watches in the Wish List, the 'Purchased' action button facilitates the seamless transition of watches from the Wish List to the Collection. When confirmed, the user is taken to the Collection page.

    Purchase Confirmation Mobile Purchase Confirmation Tablet Purchase Confirmation Desktop
    screenshot screenshot screenshot
  • Editing Watches

    If a user needs to edit a watch, they can do so via the watch's edit action button. The edit process is very similar to the add watch process, except this time any information that was already stored for the watch is prefilled into the data input form. If the watch had an image uploaded, this is also shown. Here you can change any information, add new information, or delete some information. The only fields that are required remain the Make, Movement Type, and List name.

    When the user is happy with the changes, they can click on 'Update Watch,' where they will be presented with the updated details to confirm. They can also cancel at this stage and return to the list they were viewing.

    Watch editing mobile Watch editing tablet Watch editing desktop
    screenshot screenshot screenshot

    When the details are confirmed, the watch is updated with the new information and the user is directed to the list in which the watch was saved to. As with adding a watch, the user can also click on 'Edit' to go back and amend more info or 'Cancel' to return to the previous watch list they were viewing without making any changes.

    Edit confirmation mobile Watch confirmation tablet Watch confirmation desktop
    screenshot screenshot screenshot
  • Deleting Watches

    If a user needs to delete a watch, they can do this using the 'Delete' action button. The user is then asked to confirm this action and warned that it cannot be undone. The user can click confirm, which will delete the watch and return them to the list they were viewing, or click cancel, which will return them without deleting the watch.

    Watch delete mobile Watch delete tablet Watch delete desktop
    screenshot screenshot screenshot
  • Staff Member Access Privileges

    Staff members are client users who are given access to the staff settings page. This is where you can add, edit, and delete custom movement types and lists for the users. As a staff member, you will not have access to modify the default movement types or lists; this is set up by the site admin.

    Staff settings page mobile Staff settings page tablet Staff settings page desktop
    screenshot screenshot screenshot
    • Adding a movement type or list

      To add a new movement type or list, the staff member simply types the new name in the relevant input box and clicks the 'Add' button. The new item will be added to the respective list.

      Add item mobile Add item tablet Add item desktop
      screenshot screenshot screenshot
    • Editing a movement type or list

      To edit an existing custom movement or list, the staff member clicks on the edit button for the item. A prompt appears prefilled with the current name ready for editing. The user can then either proceed with the edit by clicking 'Amend' or cancel with the 'Cancel' button. The user is also informed of any watches that would be affected by this change.

      Edit item mobile Edit item tablet Edit item desktop
      screenshot screenshot screenshot
    • Deleting a movement type or list

      To delete an existing custom movement or list, the staff member clicks on the delete button for item. A prompt appears asking them to confirm. The user can then either proceed with the deletion by clicking 'Delete' or cancel with the 'Cancel' button. The user is also informed of any watches that would be affected by this change.

      Delete item mobile Delete item tablet Deletedit item desktop
      screenshot screenshot screenshot
  • Super User Access Privileges

    The only people with super user access are the site admin/s. They will be given access to the Django admin panel. From here, they can set up and edit the default lists and movements. They can also edit and delete users. As this is a very powerful panel, client users will not be able to access this.

    Admin panel mobile Admin panel tablet Admin panel item desktop
    screenshot screenshot screenshot
  • Communication to User

    Communication to the user while they are using the site is important. It helps to let them know actions have been performed correctly, update them on navigation, and inform them if errors occur. It is also important to give a visual indication for background activity so that they do not think clicking on something did not work properly. Watch-O-Tron uses Django messages and Bootstrap spinners to fulfil this task.

    Messaging

    Messages are displayed to the user in the following circumstances:

    • All sign-in and sign-out processes
    • Switching between watch lists and pagination
    • Confirmation of add, edit, and deletion of watches
    • Confirmation of add, edit, and deletion of custom movements and lists for staff members
    • Cancellation of actions
    • Form errors

    Colour-coded messages are used for clear understanding of what a message is about:

    • Green messages are confirmation of a process completing
    • Blue messages are indicators that a process was stopped by the user (eg. cancelling the addition of a watch)
    • Red messages indicate that there has been an error

    All messages except errors are automatically dismissed after a few seconds. Error messages remain on screen and must be manually dismissed by the user so as to confirm that they have acknowledged it.

    Message Screenshot
    Sign in screenshot
    Sign out screenshot
    Switching lists to page 1 screenshot
    Switching lists to page 4 screenshot
    Switching lists with no pagination screenshot
    Adding watch screenshot
    Editing watch screenshot
    Deleting watch screenshot
    Adding staff member custom item screenshot
    Editing staff member custom item screenshot
    Deleting staff member custom item screenshot
    Cancel adding watch screenshot
    Cancel editing watch screenshot
    Cancel deleting watch screenshot
    Cancel editing staff member custom item screenshot
    Cancel deleting staff member custom item screenshot
    Form error screenshot

    Working Spinner

    A spinner is used when a user confirms the addition or editing of a watch. This is when most data is being written to the database, especially if there is also an image to upload to Cloudinary. Therefore, a spinner is shown in the button replacing the button text to inform the user that something is happening.

    screenshot

  • Easter Eggs

    There's more than meets the eye in the Watch-O-Tron. I have implemented 4 Easter eggs into the site that curious users might notice.

    Click here to reveal the hidden Easter eggs in the Watch-O-Tron.
    Last chance to change your mind.
    • Live clock: the 'O' of the main logo hides a live clock which works to the user’s local time.

      screenshot

    • Day complication: the icon for the day complication is dynamic so that it shows the current day. There is also a little extra Easter egg nod to a certain popular watch brand who uses red text on Sundays.

      screenshot

    • Date complication: the icon for the date complication is dynamic so that it shows the current date.

      screenshot

    • Moonphase complication: the icon is dynamic and shows the current phase of the moon. Data used for this is retrieved from Ephem

      screenshot

Future Features

  • User Forum

    • I would like to add a forum feature where users can communicate with each other, ask questions and post interesting things about their watches.
  • Direct Messaging

    • An addition to the forum feature would be the implementation of a direct messaging system for when privacy is required for conversations.
  • User Account Deletion

    • It would be good for a user to be able to delete their account which would in turn delete all info about them and their watches from the site.

Tools & Technologies Used

Note

I have listed both Materialize and Bootstrap as CSS frameworks used. This is because my initial design used materialize as I wanted to use features such as card reveals and floating action buttons (seen in the wireframes). However it soon became apparent that using materialize was causing more compatibility issues as I got further into development. I therefore made the decision to switch over to Bootstrap for my CSS framework.

  • Markdown Builder used to generate README and TESTING templates.
  • Git used for version control. (git add, git commit, git push)
  • GitHub used for secure online code storage.
  • Gitpod used as a cloud-based IDE for development.
  • HTML used for the main site content.
  • CSS used for the main site design and layout.
  • JavaScript used for user interaction on the site.
  • Python used as the back-end programming language.
  • Heroku used for hosting the deployed back-end site.
  • Bootstrap used as the front-end CSS framework for modern responsiveness and pre-built components.
  • Materialize used as the front-end CSS framework for modern responsiveness and pre-built components.
  • Django used as the Python framework for the site.
  • PostgreSQL by Code Institute used as the Postgres database from Code Institute.
  • Cloudinary used for online static file storage.
  • WhiteNoise used for serving static files with Heroku.
  • Gmail used for sending emails in my application.
  • Balsamiq used for creating wireframes.
  • Lucid used for creating an erd for the database models.
  • Mermaid used for creating a flowchart for the apps logic.
  • Font Awesome used for the icons.
  • ChatGPT used to help debug, troubleshoot, and explain things.

App Logic

To follow best practice, a flowchart was created for the app's logic. This was mapped out before coding began using a free version of Mermaid

Below is the mermaid flowchart of the showing the main processes of Wath-O-Tron:

---
config:
  theme: default
---
flowchart TD
    n1["watch-o-tron initialises"] --> n2["is user logged in?"]
    n2 -- no --> n3["login/register screen"]
    n3 --> n2
    n2 -- yes --> n4["user homepage"]
    n4 --> n11(["switch views collection/wishlist"]) & n10(["add new watch button"]) & n14["show collection on login"] & n16(["logout"])
    n5["retrieve collection data.<br>is watch collection empty?"] <-- query database --> n6["database"]
    n7["retrieve wishlist data.<br>is watch wishlist empty?"] <-- query database --> n6
    n5 -- no --> n8["showing watch collection<br>(card views)"]
    n9["suggest to add watch"] -- yes --> n12["new watch form"]
    n10 --> n12
    n11 -- switch to wishlist --> n7
    n11 -- switch to collection --> n5
    n7 -- no --> n13["showing wishlist<br>(card views)"]
    n7 -- yes --> n9
    n13 --> n4 & n19(["transfer watch to collection"]) & n20(["delete watch"]) & n21(["edit watch"])
    n8 --> n4 & n25(["edit watch"]) & n26(["delete watch"])
    n14 --> n5
    n5 -- yes --> n15["has user just logged in?"]
    n15 -- no --> n9
    n15 -- yes --> n7
    n16 --> n1
    n17["-Owner<br>-Slug<br>-Make<br>-Collection<br>-Model<br>-Movement Type<br>-Image<br>-Chronograph?<br>-Date?<br>-Day?<br>-GMT?<br>-World?<br>-Moon?<br>-Pwr Reserve?<br>-Tourbillon?<br>-Collection or Wishlist?"] -- User input --> n12
    n12 --> n18["confirmation"]
    n18 -- confirm addition and update database --> n6
    n18 -- edit details --> n12
    n19 --> n23["confirmation"]
    n23 -- yes update database --> n6
    n23 -- yes/no --> n13
    n20 --> n24["confirmation"]
    n24 -- yes update database --> n6
    n24 -- yes/no --> n13
    n21 <-- retrieve watch details --> n6
    n21 -- prefill data --> n22["watch edit form"]
    n22 -- confirm edits and update database --> n6
    n25 -- prefill data --> n27["watch edit form"]
    n26 --> n28["confirmation"]
    n28 -- yes/no --> n8
    n28 -- yes update database --> n6
    n27 -- confirm edits and update databse --> n6
    n25 <-- retrieve watch details --> n6
    n29["user input"] --> n27
    n30["user input"] --> n22
    n18 -- cancel and return --> n13 & n8
    n22 -- return --> n13
    n27 -- return --> n8
    n6@{ shape: db}



    style n1 stroke-width:4px,stroke-dasharray: 5,fill:#FFF9C4,color:#000000,stroke:#000000
    style n2 fill:#FFF9C4,stroke-width:4px,stroke-dasharray: 5,stroke:#000000
    style n3 fill:#FFFFFF,stroke:#000000,stroke-width:4px,stroke-dasharray: 0
    style n4 fill:#FFFFFF,stroke-width:4px,stroke-dasharray: 0,stroke:#000000
    style n11 color:#000000,fill:#FFD600,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n10 fill:#FFD600,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n14 fill:#FFF9C4,stroke-width:4px,stroke-dasharray: 5,stroke:#000000
    style n16 stroke:#000000,fill:#D50000,color:#FFFFFF,stroke-width:4px,stroke-dasharray: 0
    style n5 fill:#FFF9C4,stroke-width:4px,stroke-dasharray: 5,stroke:#000000
    style n7 fill:#FFF9C4,stroke:#000000,stroke-width:4px,stroke-dasharray: 5
    style n8 stroke:#000000,fill:#FFFFFF,stroke-width:4px,stroke-dasharray: 0
    style n9 color:#FFFFFF,fill:#2962FF,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n12 fill:#2962FF,color:#FFFFFF,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n13 stroke:#000000,fill:#FFFFFF,stroke-width:4px,stroke-dasharray: 0
    style n19 fill:#FFD600,stroke:#000000,stroke-width:2px,stroke-dasharray: 0
    style n20 color:#FFFFFF,fill:#D50000,stroke:#000000,stroke-width:2px,stroke-dasharray: 0
    style n21 fill:#FFD600,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n25 stroke:#000000,fill:#FFD600,stroke-width:2px,stroke-dasharray: 0
    style n26 fill:#D50000,color:#FFFFFF,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n15 fill:#FFF9C4,stroke:#000000,stroke-width:4px,stroke-dasharray: 5
    style n17 color:#000000,stroke-width:2px,stroke-dasharray: 0,stroke:#000000,fill:#BBDEFB
    style n18 fill:#00C853,color:#FFFFFF,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n23 fill:#00C853,color:#FFFFFF,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n24 color:#FFFFFF,fill:#00C853,stroke:#000000,stroke-width:2px,stroke-dasharray: 0
    style n22 stroke:#000000,fill:#2962FF,color:#FFFFFF,stroke-width:2px,stroke-dasharray: 0
    style n27 fill:#2962FF,color:#FFFFFF,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n28 color:#FFFFFF,fill:#00C853,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n29 fill:#BBDEFB,stroke-width:2px,stroke-dasharray: 0,stroke:#000000
    style n30 fill:#BBDEFB,stroke:#000000,stroke-width:2px,stroke-dasharray: 0
Loading

Source in live editor: Watch-O-Tron Mermaid flowchart

Database Design

Entity Relationship Diagrams (ERD) help to visualize database architecture before creating models. Understanding the relationships between different tables can save time later in the project.

class WatchList(models.Model):
    class Meta:
        ordering = ['list_order', 'friendly_name']

    list_name = models.CharField(
        max_length=100, unique=True, blank=True, null=True
    )
    friendly_name = models.CharField(
        max_length=100, unique=True, verbose_name=' name'
    )
    list_order = models.IntegerField(default=1000)

    def __str__(self):
        return self.friendly_name

    def save(self, *args, **kwargs):
        # creating url friendly name from user entered friendly_name
        self.list_name = slugify(self.friendly_name)
        super().save(*args, **kwargs)


class WatchMovement(models.Model):
    movement_name = models.CharField(
        max_length=100, unique=True, verbose_name=' name'
    )

    def __str__(self):
        return self.movement_name


class Watch(models.Model):
    class Meta:
        verbose_name_plural = 'Watches'

    # general watch details
    owner = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='watch_owner'
    )
    list_name = models.ForeignKey(
        WatchList, on_delete=models.CASCADE, related_name='watch_list'
    )
    movement_type = models.ForeignKey(
        WatchMovement, on_delete=models.CASCADE, related_name='watch_movement'
    )
    make = models.CharField(max_length=100, null=False, blank=False)
    collection = models.CharField(max_length=100, blank=True)
    model = models.CharField(max_length=100, blank=True)
    movement_model = models.CharField(max_length=50, blank=True)
    image = CloudinaryField(
        'image', default='placeholder', asset_folder='/wot_watches/'
    )
    # complications
    complication_chronograph = models.BooleanField(default=False)
    complication_date = models.BooleanField(default=False)
    complication_day = models.BooleanField(default=False)
    complication_gmt = models.BooleanField(default=False)
    complication_world_timer = models.BooleanField(default=False)
    complication_moonphase = models.BooleanField(default=False)
    complication_power_reserve = models.BooleanField(default=False)
    complication_tourbillon = models.BooleanField(default=False)

    def __str__(self):
        return f'{self.make} {self.collection} {self.model}'

    def delete(self, *args, **kwargs):
        # checking to see if the image is a placeholder and delete image if not
        if self.image != 'placeholder':
            public_id = self.image.public_id
            cloudinary.uploader.destroy(public_id)
        # proceed with normal deletion
        super().delete(*args, **kwargs)

I created an ERD to help code the models for the database. This was done using a free version of Lucid chart

erd-chart

I have also used pygraphviz and django-extensions to auto-generate an ERD.

The steps taken were as follows:

  • In the terminal: sudo apt update
  • then: sudo apt-get install python3-dev graphviz libgraphviz-dev pkg-config
  • then type Y to proceed
  • then: pip3 install django-extensions pygraphviz
  • in my settings.py file, I added the following to my INSTALLED_APPS:
INSTALLED_APPS = [
    ...
    'django_extensions',
    ...
]
  • back in the terminal: python3 manage.py graph_models -a -o erd.png
  • dragged the new erd.png file into my documentation/ folder
  • removed 'django_extensions', from my INSTALLED_APPS
  • finally, in the terminal: pip3 uninstall django-extensions pygraphviz -y git erd source: medium.com

Agile Development Process

GitHub Projects

GitHub Projects served as an Agile tool for this project. It isn't a specialized tool, but with the right tags and project creation/issue assignments, it can be made to work.

Through it, user stories, issues, and milestone tasks were planned, then tracked on a weekly basis using the basic Kanban board.

screenshot

I also created an overview page where I could easily see at a glance the current progress in development. This allowed me to track start and finish dates along with adding prioritisation for bugs.

screenshot

GitHub Issues

GitHub Issues served as an another Agile tool. There, I used my own User Story Template to manage user stories.

It also helped with milestone iterations on a weekly basis.

MoSCoW Prioritization

I've decomposed my Epics into stories prior to prioritizing and implementing them. Using this approach, I was able to apply the MoSCow prioritization and labels to my user stories within the Issues tab.

  • Must Have: guaranteed to be delivered (max 60% of stories)
  • Should Have: adds significant value, but not vital (the rest ~20% of stories)
  • Could Have: has small impact if left out (20% of stories)
  • Won't Have: not a priority for this iteration

The GitHub projects helped keep track of this with the creation of a graph.

screenshot

Testing

Note

For all testing, please refer to the TESTING.md file.

Deployment

The live deployed application can be found deployed on Heroku.

PostgreSQL Database

This project uses a Code Institute PostgreSQL Database.

To obtain my own Postgres Database from Code Institute, I followed these steps:

  • Signed-in to the CI LMS using my email address.
  • An email was sent to me with my new Postgres Database.

Caution

  • PostgreSQL databases by Code Institute are only available to CI Students.
  • You must acquire your own PostgreSQL database through some other method if you plan to clone/fork this repository.
  • Code Institute students are allowed a maximum of 8 databases.
  • Databases are subject to deletion after 18 months.

Cloudinary API

This project uses the Cloudinary API to store media assets online, due to the fact that Heroku doesn't persist this type of data.

To obtain your own Cloudinary API key, create an account and log in.

  • For Primary interest, you can choose Programmable Media for image and video API.
  • Optional: edit your assigned cloud name to something more memorable.
  • On your Cloudinary Dashboard, you can copy your API Environment Variable.
  • Be sure to remove the CLOUDINARY_URL= as part of the API value; this is the key.

Gmail API

This project uses Gmail to handle sending passwrod reset emails to users.

Once you've created a Gmail (Google) account and logged-in, follow these series of steps to get your project connected.

  • Click on the Account Settings (cog icon) in the top-right corner of Gmail.
  • Click on the Accounts and Import tab.
  • Within the section called "Change account settings", click on the link for Other Google Account settings.
  • From this new page, select Security on the left.
  • Select 2-Step Verification to turn it on. (verify your password and account)
  • Once verified, select Turn On for 2FA.
  • Navigate back to the Security page, and you'll see a new option called App passwords (search for it at the top, if not).
  • This might prompt you once again to confirm your password and account.
  • Select Mail for the app type.
  • Select Other (Custom name) for the device type.
    • Any custom name, such as "Django" or p4_watch-o-tron
  • You'll be provided with a 16-character password (API key).
    • Save this somewhere locally, as you cannot access this key again later!
    • If your 16-character password contains spaces, make sure to remove them entirely.
    • SUPPORTEMAILPASSWORD = user's 16-character API key
    • SUPPORTEMAIL = user's own personal Gmail email address
    • SUPPORTEMAILHOST = smtp.gmail.com if using Gmail.

Heroku Deployment

This project uses Heroku, a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud.

Deployment steps are as follows, after account setup:

  • Select New in the top-right corner of your Heroku Dashboard, and select Create new app from the dropdown menu.
  • Your app name must be unique, and then choose a region closest to you (EU or USA), and finally, select Create App.
  • From the new app Settings, click Reveal Config Vars, and set your environment variables.

Important

This is a sample only; you would replace the values with your own if cloning/forking my repository.

Key Value
DATABASE_URL user's own value
SECRET_KEY user's own value
CLOUDINARY_URL user's own value
CLOUDINARY_NAME user's own value
CLOUDINARY_API user's own value
CLOUDINARY_SECRET user's own value
SUPPORTEMAIL user's own value
SUPPORTEMAILPASSWORD user's own value
SUPPORTEMAILHOST user's own value
DISABLE_COLLECTSTATIC 1 (this is temporary, and can be removed for the final deployment)

Heroku needs additional files in order to deploy properly.

  • requirements.txt
  • Procfile

You can install this project's requirements (where applicable) using:

  • pip3 install -r requirements.txt

If you have your own packages that have been installed, then the requirements file needs updated using:

  • pip3 freeze --local > requirements.txt

The Procfile can be created with the following command:

  • echo web: gunicorn app_name.wsgi > Procfile
  • replace app_name with the name of your primary Django app name; the folder where settings.py is located

For Heroku deployment, follow these steps to connect your own GitHub repository to the newly created app:

Either:

  • Select Automatic Deployment from the Heroku app.

Or:

  • In the Terminal/CLI, connect to Heroku using this command: heroku login -i
  • Set the remote for Heroku: heroku git:remote -a app_name (replace app_name with your app name)
  • After performing the standard Git add, commit, and push to GitHub, you can now type:
    • git push heroku main

The project should now be connected and deployed to Heroku!

Local Deployment

This project can be cloned or forked in order to make a local copy on your own system.

For either method, you will need to install any applicable packages found within the requirements.txt file.

  • pip3 install -r requirements.txt.

You will need to create a new file called env.py at the root-level, and include the same environment variables listed above from the Heroku deployment steps.

Important

This is a sample only; you would replace the values with your own if cloning/forking my repository.

Sample env.py file:

import os

os.environ.setdefault("DATABASE_URL", "user's own value")
os.environ.setdefault("SECRET_KEY", "user's own value")
os.environ.setdefault("CLOUDINARY_URL", "user's own value")
os.environ.setdefault("CLOUDINARY_NAME", "user's own value")
os.environ.setdefault("CLOUDINARY_API", "user's own value")
os.environ.setdefault("CLOUDINARY_SECRET", "user's own value")
os.environ.setdefault("SUPPORTEMAIL", "user's own value")
os.environ.setdefault("SUPPORTEMAILPASSWORD", "user's own value")
os.environ.setdefault("SUPPORTEMAILHOST", "user's own value")

# local environment only (do not include these in production/deployment!)
os.environ.setdefault("DEVELOPMENT", "True")

Once the project is cloned or forked, in order to run it locally, you'll need to follow these steps:

  • Start the Django app: python3 manage.py runserver
  • Stop the app once it's loaded: CTRL+C or ⌘+C (Mac)
  • Make any necessary migrations: python3 manage.py makemigrations
  • Migrate the data to the database: python3 manage.py migrate
  • Create a superuser: python3 manage.py createsuperuser
  • Load fixtures (if applicable): python3 manage.py loaddata file-name.json (repeat for each file)
  • Everything should be ready now, so run the Django app again: python3 manage.py runserver

Cloning

You can clone the repository by following these steps:

  1. Go to the GitHub repository
  2. Locate the Code button above the list of files and click it
  3. Select if you prefer to clone using HTTPS, SSH, or GitHub CLI and click the copy button to copy the URL to your clipboard
  4. Open Git Bash or Terminal
  5. Change the current working directory to the one where you want the cloned directory
  6. In your IDE Terminal, type the following command to clone my repository:
    • git clone https://github.com/apeskinian/p4_watch-o-tron.git
  7. Press Enter to create your local clone.

Alternatively, if using Gitpod, you can click below to create your own workspace using this repository.

Open in Gitpod

Please note that in order to directly open the project in Gitpod, you need to have the browser extension installed. A tutorial on how to do that can be found here.

Forking

By forking the GitHub Repository, we make a copy of the original repository on our GitHub account to view and/or make changes without affecting the original owner's repository. You can fork this repository by using the following steps:

  1. Log in to GitHub and locate the GitHub Repository
  2. At the top of the Repository (not top of page) just above the "Settings" Button on the menu, locate the "Fork" Button.
  3. Once clicked, you should now have a copy of the original repository in your own GitHub account!

Local VS Deployment

There are no differences between the local and deployed version of the site.

Credits

Content

Source Location Notes
Markdown Builder README and TESTING tool to help generate the Markdown files
Bootrap Documentation entire site using bootstrap
Medium - How to Style Your Django Forms manage watch forms help on manually styling Django forms
Stack Overflow entire site adding django template variable to img src
Codepen clock in main logo base code for working clock
Ephem PyPI watch object moonphase icons package used to get last new moon date
Cloudinary entire site hosting user uploaded images
WhiteNoise entire site hosting static files on Heroku temporarily

Media

Source Location Type Notes
Favicon Generator entire site favicon icon generated from my own png
Vecteezy watch objects image placeholder image for watches
Font Awesome watch objects image chronograph complication icon
Font Awesome watch objects image gmt complication icon
Font Awesome watch objects image world timer complication icon
Clop Image Optimization entire site software used to optimise all media
Cleanshot X README and TESTING software used for screenshots and video capture

Custom Media

The following elements were created by myself.

Element Location Notes
Favicon favicon for all pages I created the png that was uploaded to Favicon Generator
Day Complication icon watch objects 31 variants that change dynamically based on the current day
Date Complication icon watch objects 7 variants that change dynamically based on the current date
Moonphase Complication icon watch objects 8 variants that change dynamically based on the current moonphase
Power Reserve Complication icon watch objects
Tourbillon Complication icon watch objects

Acknowledgements

  • I would like to thank my Code Institute mentor, Tim Nelson for his support throughout the development of this project.
  • I would like to thank the Code Institute tutor team for their assistance with troubleshooting and debugging some project issues.
  • I would like to thank the Code Institute Slack community for the moral support; it kept me going during periods of self doubt and imposter syndrome.
  • I would like to thank my daughter Niamh, my sisters Laura & Natalie and my whole family for believing in me, and supporting me while making this transition into software development.

About

Project 4 Full Stack - Watch-O-Tron

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages