Documentation - cse110-sp24-group23/dev-journal GitHub Wiki
Basic Usage
The implementation can be found in the src folder, which holds the HTML, CSS, and JS files for each of the pages, assets and icons, as well as the implementation of the backend storage.
For more information, please check our onboarding instructions.
Code Map
Documentation for method definitions
Backend-storage
We created a couple different apis and object constructor classes to be able to decouple our storage implementations from its use. We have the following backend files: accomplishments-api.js
, accomplishments-class.js
, mde-mode-api.js
, record-class.js
, records-api.js
.
Starting with accomplishments, in the app, users can add accomplishments in the daily logs to mark large tasks that were finally completed on that date. Then, in the Accomplishments page, they can view them by month, year, or all-time to see a summary of major accomplishments that they could then show to an employer. The AccomplishmentsObj
class (in accomplishments-class.js
creates an object that stores all accomplishments from a single date. It has content
(array of strings) and date
(Date) fields that are passed in through the constructor, as well as an internally created id
that is the calculated by date.getTime(). Note: the date should only include the year, month, day, not hours, minutes, seconds, or milliseconds.
Next, the LocalStorageAccomplishmentsApi
class (in accomplishments-api.js
) provides functions as a way to interact with the CRUD functionality for these objects. Note: do not use getter functions to check if an accomplishment exists. Instead, use the hasAccomplishmentsObjByDate
function that is explicitly designed for checking that.
Records work in much the same way as accomplishments, but they are slightly more complex. A Record object has a type
field that must be set. A Record can be of type "note" or "log", and depending on which one, it will have different fields defined. For notes, a Record of type "log" will have a field1
(string), field2
(string), hours
(Number), title
(string), and date
(Date) all set through the constructor. Note: the date should only contain year, number, and day for a log, since the exact time doesn't matter for that, only the date does. An id
is also set internally by taking date.getTime(). A record of type "note" will only have a field1
, title
, and date
, although this date will include hours, minutes, seconds, and milliseconds along with the other expected values (year, month, date) because the exact creation time of a note does matter. Records also have internally set created
and updated
fields which can in the future be used to filter/sort notes by created or updated dates.
Finally, after using the Record
class to create a new Record, the LocalStorageRecordsApi
class (in records-api.js
) provides functions as a way to interact with the CRUD functionality for these objects. As with the accomplishments api, you should not use getter functions to check if a record exists. Use the hasRecordBy functions, where you can check by date or id.
The final backend file is mde-mode-api.js
, which is used to get or set the status of whether or not the user wants there to be markdown editing functionality or not for the notes and daily log. The main reason for disabling markdown editing is for keyboard-only users, who would get stuck in a markdown editor due to not being able to tab or Enter out of it, since tabbing and Entering just create indents or new lines in the markdown editors.
Calendar
When you open Noted, you land on calendar.html
. The calendar.html
has a table with one header row as well as a body with 6 rows and 7 columns. The header row has the days of the week. The rest of the rows are populated based on the current month.
When the calendar page is loaded, calendar.js
makes a new instance Calendar
of the Calendar class, located in calendar-class.js
. The days of the current month are populated using the calendar.populateMonthView()
function. populateMonthView()
gets the rollover dates from the previous month, the dates from the current month and the rollover dates for the next month, and makes it into a list of dates: datesList
. The dates of the current month from datesList
are populated as is. If the date is part of the previous or the next month, a class name rollover-date
is added to the HTML element so that they can be grayed out.
When the dates are being populated in populateMonthView()
, we also check the following: if a record or accomplishments exists for that date in the local storage, or if that date is the current date. If a date matches the current day, we add the class name current-date
to the HTML element so that it can be highlighted in a darker blue from the rest of the calendar. If a record exists in the local storage for that date, we add a checkmark icon indicating that the daily log was filled out. If an accomplishments object exists in the local storage for that date, we add an accomplishments icon indicating that there are accomplishments logged for that day.
When the previous month button is clicked, prevMonthView()
updates the current month and year variables and populates the months based on that. Similarly when the next month button is clicked, nextMonthView()
updates the current month and year variables and populates the months based on that.
Daily Log
When you click on a date in the calendar, it takes you to that date's daily log. If a record object for the daily log already exists, the record object is pulled out of the local storage and it is stored in the session storage as the current-record
. Otherwise, a new record object is created using the Record class and is stored in the session storage as the current-record
.
When the daily log page is loaded, we pull the current-record
object from the session storage. If the record object is not found in the session storage, then local storage is checked. If the record object exists in local storage, then it is pulled from local storage. If the record object doesn't exist there either, then a new instance of the Record class is created. Using the populateDefaultLog
function, the record is populated into the daily log page.
The text areas in the daily log HTML have SimpleMDE objects applied to them to create functional Markdown editors. These objects are defined in simpleMDE.js
, and are customized for the purposes of Noted. They are set on/off depending on the statusMDE
, set by the user in the settings page, and retrieved/set internally through the mde-mode-api.js
functionality.
When the save log button is clicked, we check if the record object exists in the local storage. If it does not, we save the record object in the Records list in local storage in the function createRecord
located in record-api.js
. All the information from the textareas and the inputs are pulled and the record object is updated. After that, the record is updated in the local storage using updateRecord
from record-api.js
. When the delete log button is clicked, we check if the record object exists in the local storage. If it does, a message is displayed to ask for confirmation. If accepted, the daily log is deleted from the local storage using the function deleteRecord
from record-api.js
.
To add an accomplishment, you first need to type in the accomplishment into the input box and then click on add accomplishment button. When the button is clicked, a new element is created and the entered text is populated into it. The element also has edit, done and delete buttons attached to it to give accomplishments CRUD functionality. When the save log button is clicked, we check if any accomplishments exist. If they do the record object's has-accomplishment
variable is set to true. We check to see if any accomplishments for the date exist in the local storage, if they do we update the accomplishments. Otherwise, we create a new AccomplishmentsObj
, and add the accomplishments to the local storage.
Navigation Bar
For the navigation bar, we created a component that could be displayed on each page. We have links for the calendar page, today's daily log, notes page and accomplishments page. We iterate over all the links in the navigation bar to find the active link.
When the link to the daily log is clicked on the nav bar, the link should be highlighted to show that today's log is being displayed. However, when any other log is being displayed, the link on the nav bar should not be highlighted. To implement this, when a link on the navigation bar is clicked, we check to see if the session storage is empty. This is done because the session storage is not null when a date is clicked through the calendar page. So, the today's page is only highlighted when the date of the session storage record is the same as today's date.
Notes Page
For the notes page, we created a custom HTML element called a note-element
. These represent the information of a note in small note cards that somewhat resemble sticky notes. For each note in the local storage, a new note-element
is added to the page to display its information. The note-element is populated with information from a Record
of type="note"
.
When the user clicks on a note to edit it, or clicks the "Add Note" button, we use the function _displayNoteEditor
to show the note editor. This editor is used to create new notes or edit existing ones. this function is broken down into two cases: create or update. If the editor does not yet exist, we create it, otherwise we hide/display it. When it is created, we also apply a simpleMDE object to the content field of the note editor if the user has not disabled markdown editing. Once the "Save" button is pressed, if they were editing a note, we remove the old note from the page, and just load in the most recently edited note. Otherwise, if the user was just adding a new note, we only bring in the newest created note. This avoids reloading every note from local storage in order to keep it efficient.
When the user clicks the "Delete Note" button, all notes display a trash icon and no longer open the note editor when they are clicked. This is done through adding and removing event listeners. The trash icons have a hidden trash icon by default. When the user clicks the button to delete notes, we remove the editing notes event listener and display the trash icons, adding an event listener for the icon to be clicked on. When the "Done Deleting" button is pressed, the reverse happens: we add back the notes click to edit listeners and remove the trash listeners, while hiding the icon.
Accomplishments Page
For the Accomplishments page, we utilize the accomplishments-api.js
file in src/backend-storage
to get a list of all AccomplishmentsObj
(Objects that store accomplishments for a single date). Once those are retrieved, we work on populating the table with them. We first sort all the accomplishments objects by date (oldest first), with no filters. From there, we save that array so that all future sorts by newest or oldest can be done by reversing that array which is much faster than an O(nlogn) sort of unsorted objects.
From there, we have a function that takes in an AccomplishmentsObj array and display options and returns a filtered/sorted one based on the sort and filter requested. We run this, passing in the appropriate options, each time a new option in the sort or filter option is selected in the UI. Then, after that is done, we run populateTable
, which is a function that takes in an AccomplishmentsObj array, and then splits each accomplishment object into its contents to get individual accomplishments which it then uses to populate each row in the table.