{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"State Tree Glossary","llmstxt":{"hide":true}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"state-tree-glossary","__idx":0},"children":["State Tree Glossary"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"glossary-of-terms-in-the-tidepool-uploaders-state-tree","__idx":1},"children":["Glossary of Terms in the Tidepool Uploader's State Tree"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"preliminary","__idx":2},"children":["Preliminary"]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["PWD"]},": Person With Diabetes (or, conveniently enough for us at Tidepool, Person With Data). Used as a shorthand for a user that has a Tidepool account ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["with"]}," data storage, as opposed to a Tidepool user (such as a clinic worker, diabetes educator, endocrinologist etc.) whose account is not set up for data storage."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"user-related-state","__idx":3},"children":["User-Related State"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All the state that is driven by user information and/or the login process is handled in the reducers in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["app/reducers/users.js"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"allusers","__idx":4},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allUsers"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allUsers"]}," property is an object keyed by the user IDs of the logged-in user as well as all the PWDs the logged-in user has permissions to upload for. The information stored under each ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userID"]}," is all the account and profile information accessible to the logged-in user for that user."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In essence, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allUsers"]}," object is where all user information accessible to the logged-in user is stored. Keeping all this information in one place keyed by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]}," allows us to only reference users by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]}," elsewhere in the state tree, thus maintaining a \"normalized\" state tree with a single source of truth for user-related information. (Cf. Dan Abramov's presentation of the \"normalization\" problem in the README for his ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/gaearon/normalizr#the-problem"},"children":["normalizr library"]},".) Whenever a component needs additional information (that is, beyond ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]},") about a user, that information can be retrieved via lookup under the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Examples of properties that may be encoded in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allUsers"]}," for a particular user include ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fullName"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["emails"]},", a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["patient"]}," object that itself includes the PWD's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["birthday"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["diagnosisData"]},". Also see the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/uploader/state/examplestatetree"},"children":["example state tree"]}," for full examples."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"memberships","__idx":5},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["memberships"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["*The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["memberships"]}," property is an object keyed by the user IDs of the logged-in user as well as all the PWDs the logged-in user has some permissions on. Each entry contains a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["permissions"]}," object which in turn has keys representing various permissions, each of which will have an empty object and the existence of the key indicates the presence of that permission. Some permissions include ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["custodian"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["view"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"loggedinuser","__idx":6},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["loggedInUser"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["loggedInUser"]}," encodes the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userID"]}," of the currently logged-in user."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If no user is (yet) logged in, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["loggedInUser"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"loginerrormessage","__idx":7},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["loginErrorMessage"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["loginErrorMessage"]}," encodes the error message if there is an error on an attempt to log in."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If there has not (yet) been a login attempt or login proceeded without error, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["loginErrorMessage"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"updateprofileerrormessage","__idx":8},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updateProfileErrorMessage"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updateProfileErrorMessage"]}," encodes the error message if there is an error on an attempt to update the user's profile information."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If there has not (yet) been an error updating profile information or profile information update proceeded without error, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updateProfileErrorMessage"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"updateprofileerrordismissed","__idx":9},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updateProfileErrorDismissed"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updateProfileErrorDismissed"]}," is a flag indicating whether the user has dismissed the displayed ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadProfileErrorMessage"]},"."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the user has not dismissed the error or if there has been no error to dismiss, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updateProfileErrorDismissed"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},". If the user has dismissed an existing error, the value is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"createcustodialaccounterrormessage","__idx":10},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createCustodialAccountErrorMessage"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createCustodialAccountErrorMessage"]}," encodes the error message if there is an error on an attempt to create a new custodial account."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If there has not (yet) been an error creating a custodial account or account creation proceeded without error, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createCustodialAccountErrorMessage"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"createcustodialaccounterrordismissed","__idx":11},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createCustodialAccountErrorDismissed"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createCustodialAccountErrorDismissed"]}," is a flag indicating whether the user has dismissed the displayed ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createCustodialAccountErrorMessage"]},"."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the user has not dismissed the error or if there has been no error to dismiss, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createCustodialAccountErrorDismissed"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]},". If the user has dismissed an existing error, the value is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"targetdevices","__idx":12},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["targetDevices"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["targetDevices"]}," is an object keyed by the user IDs of all the PWDs the logged-in user has permissions to upload for (including the logged-in user, if applicable). The information stored under each ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]}," is an array of the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deviceKey"]},"s selected for that user as potential sources of data to upload to the Tidepool cloud."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"targettimezones","__idx":13},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["targetTimezones"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["targetTimezones"]}," is an object keyed by the user IDs of all the PWDs the logged-in user has permissions to upload for (including the logged-in user, if applicable). The information stored under each ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]}," is a string timezone name (from the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://www.iana.org/time-zones"},"children":["IANA Time Zone Database"]}," by way of the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://momentjs.com/timezone/"},"children":["Moment Timezone"]}," JavaScript library)."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the future we plan to support the possibility of selecting a timezone for each device a user has selected as a source of data to upload to Tidepool. When we introduce such support, we will change the value of the information stored under each ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]}," in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["targetTimezones"]}," to an object keyed by the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deviceKey"]},"s selected by the user."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"targetusersforupload","__idx":14},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["targetUsersForUpload"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["targetUsersForUpload"]}," is an array consisting of the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]},"s of all the PWDs the logged-in user has permissions to upload for (including the logged-in user, if applicable)."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This array drives the user selection dropdown menu that provides the interface for setting and changing the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"uploadtargetuser","__idx":15},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The propery ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]}," encodes the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]}," (for lookup in the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#allusers"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allUsers"]}]}," branch of the state tree) of the PWD currently selected as the target for data upload."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The combination of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetDevice"]}," provides the path into ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadsByUser"]}," to the upload currently in progress, if any."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"current-upload-related-state","__idx":16},"children":["(Current) Upload-Related State"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All the state that is driven by the current (i.e., in progress) or recent upload(s) is handled in the reducers in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["app/reducers/uploads.js"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"uploadprogress","__idx":17},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadProgress"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadProgress"]}," property is an object with two keys: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["percentage"]}," to record the percentage towards completion of the current upload in progress and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["step"]}," to encode the current step in the upload sequence (e.g., device detection, device read, POSTing data to the Tidepool data ingestion API). Optionally a third key, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["isFirstUpload"]},", can be used to indicate that the upload is the first upload from a device. This is useful for delta uploads, to display a message that the first upload will take longer than subsequent uploads."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When there is not an upload in progress, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadProgress"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"uploadsbyuser","__idx":18},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadsByUser"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadsByUser"]}," property is an object keyed by the user IDs of all the PWDs the logged-in user has permissions to upload for (including the logged-in user, if applicable). Within each user ID is another object keyed by the devices that user has selected to upload data from, if any. The information stored at each userId, deviceKey path is semi-ephemeral information about the state of current and recent uploads."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["One example of a property that is encoded in the object at the termination of each ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userId"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deviceKey"]}," path is the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["history"]}," of the user's uploading for that device, which is an array of objects with up to a maximum of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["start"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["finish"]}," timestamps and a boolean ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]}," to encode whether the upload was successful. Other examples are additional boolean flags regarding the upload's state: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["completed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["failed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["successful"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploading"]},". If an upload failed due to an error, the error object itself is included in an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]}," field. For block-mode devices, there are additional flags and fields such as boolean flags for ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["choosingFile"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["readingFile"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["file"]}," object encoding the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data"]}," from a selected file."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"uploadtargetdevice","__idx":19},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetDevice"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetDevice"]}," encodes the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["key"]}," (for lookup in the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#devices"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["devices"]}]}," branch of the state tree) of the device currently being uploaded when an upload is in progress."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When an upload is ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["not"]}," in progress, the value of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetDevice"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},". The combination of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetDevice"]}," provides the path into ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadsByUser"]}," to the upload currently in progress, if any."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"all-other-app-state","__idx":20},"children":["All Other App State"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All other app state is handled in the reducers in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["app/reducers/misc.js"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"blipurls","__idx":21},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blipUrls"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blipUrls"]}," is an object with three properties: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["forgotPassword"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signUp"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["viewDataLink"]},", all URLs for Tidepool's webapp blip."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["forgotPassword"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signUp"]}," links are built as part of the app initialization step for the configured or chosen server environment (the default is production)."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["viewDataLink"]}," is built every time the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]}," is chosen or changed."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["NB:"]}," Storing these URLs as state is not ideal. Both the forgot password and sign-up URLs are essentially ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["derived"]}," state - derived from a combination of route paths (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/signup"]},"), which are constants, and a single piece of state - the server environment. The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["viewDataLink"]}," is also derived state from a combination of route paths, the server environment, and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]},". For now, we are keeping these URLs in the state tree because we do ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["not"]}," represent the server environment in the state tree."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"devices","__idx":22},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["devices"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["devices"]}," property on the state tree is an object keyed by the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["id"]}," of each device (or data source) supported by the Tidepool Uploader."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["devices"]}," ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["almost"]}," does not belong in the state tree at all, because it is ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["almost"]}," a constant. However, it is subject to filtering based on operating system; this filtering happens as part of the app initialization step when a user launches the Tidepool Uploader. The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enabled"]}," - itself an object with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mac"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["win"]}," as its keys - encodes the devices Tidepool currently support on each platform."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The properties of each \"device\" in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["devices"]}," should be fairly self-explanatory. For example, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["instructions"]}," property stores the text that appears in the UI under each device name to give the user some indication of how to proceed (e.g., what type of cable is required to connect a particular device)."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"dropdown","__idx":23},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["dropdown"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The Tidepool Uploader includes a dropdown menu, which is accessible after logging in by clicking on the area where the logged-in user's name is displayed in the upper-right corner. The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["dropdown"]}," in the state tree encodes whether this menu is currently in its open (dropped-down) state (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},") or closed and hidden (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]},")."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"unsupported","__idx":24},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unsupported"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unsupported"]}," encodes whether the running version of the Tidepool Uploader is outdated from the perspective of Tidepool's data ingestion API. ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["This property defaults to true"]},"; in other words, any instance of the uploader is assumed to be outdated and unsupported until it proves itself otherwise."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To ensure the highest possible standards of data quality, it is very important for us at Tidepool to prevent uploaders that have been succeeded by newer versions from uploading to the Tidepool cloud. To this end, we have implemented an \"info\" endpoint on our data ingestion API that responds with (among other things) the minimum version of the Tidepool Uploader that the data ingestion API will accept data from."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"working","__idx":25},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["working"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["working"]}," property is an object with a small handful of keys that record the app's current state with respect to certain asynchronous actions."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The properties ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["initializingApp.inProgress"]}," (which defaults to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},") and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["checkingVersion.inProgress"]}," serve to prevent rendering the warning message about the Tidepool Uploader being unsupported before the application has finished checking against the Tidepool data ingestion API to determine whether it is outdated and unsupported. (See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#unsupported"},"children":["unsupported"]}," above, taking care to note that ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unsupported"]}," defaults to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},", so without some other indicator(s) of the app's state with respect to validation of the current version against the Tidepool data ingestion API, the \"uploader unsupported\" warning message would render immediately.)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["checkingElectronUpdate.inProgress"]}," is used to indicate whether or not the Electron auto-update system is currently awating the message from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["main"]}," Electron process indicating whether or not an update is currently available."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Finally, the property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploading.inProgress"]}," is used to disable certain UI features while an upload is in progress. When ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploading.inProgress"]}," is true, the dropdown menu for selecting the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["uploadTargetUser"]}," as well as the link to \"Choose devices\" in the dropdown menu are disabled until the current upload is completed, as changing the target user for upload and/or the devices chosen for upload while an upload is in progress for a particular user and device is not supported behavior."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"state-relating-to-application-updates","__idx":26},"children":["State relating to application updates"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"electronupdatemanualchecked","__idx":27},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateManualChecked"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateManualChecked"]}," encodes whether the current check for updates to the Electron application was initiated by a user or was done automatically"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The update system needs to differentiate manually initiated update checks vs. update checks that happen automatically (like on application launch and periodic background checks) in order to provide proper messaging to the user in each situation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"electronupdateavailabledismissed","__idx":28},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateAvailableDismissed"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateAvailableDismissed"]}," encodes whether the current notification for an update to the Electron application was dismissed by a user"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This property is used to ensure that users are not notified repeatedly that an update is available if they have already dismissed the notification once."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"electronupdateavailable","__idx":29},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateAvailable"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateAvailable"]}," encodes whether there is an update to the currently running Electron application or not"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This property is true when the update system check for updates has finished and there is an update available."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"electronupdatedownloaded","__idx":30},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateDownloaded"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["The property ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["electronUpdateDownloaded"]}," encodes whether an available update to the currently running Electron application has been downloaded and is ready to install"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This property is true when the update system has finished downloading an available update."]}]},"headings":[{"value":"State Tree Glossary","id":"state-tree-glossary","depth":1},{"value":"Glossary of Terms in the Tidepool Uploader's State Tree","id":"glossary-of-terms-in-the-tidepool-uploaders-state-tree","depth":2},{"value":"Preliminary","id":"preliminary","depth":3},{"value":"User-Related State","id":"user-related-state","depth":3},{"value":"allUsers","id":"allusers","depth":4},{"value":"memberships","id":"memberships","depth":3},{"value":"loggedInUser","id":"loggedinuser","depth":4},{"value":"loginErrorMessage","id":"loginerrormessage","depth":4},{"value":"updateProfileErrorMessage","id":"updateprofileerrormessage","depth":4},{"value":"updateProfileErrorDismissed","id":"updateprofileerrordismissed","depth":4},{"value":"createCustodialAccountErrorMessage","id":"createcustodialaccounterrormessage","depth":4},{"value":"createCustodialAccountErrorDismissed","id":"createcustodialaccounterrordismissed","depth":4},{"value":"targetDevices","id":"targetdevices","depth":4},{"value":"targetTimezones","id":"targettimezones","depth":4},{"value":"targetUsersForUpload","id":"targetusersforupload","depth":4},{"value":"uploadTargetUser","id":"uploadtargetuser","depth":4},{"value":"(Current) Upload-Related State","id":"current-upload-related-state","depth":3},{"value":"uploadProgress","id":"uploadprogress","depth":4},{"value":"uploadsByUser","id":"uploadsbyuser","depth":4},{"value":"uploadTargetDevice","id":"uploadtargetdevice","depth":4},{"value":"All Other App State","id":"all-other-app-state","depth":3},{"value":"blipUrls","id":"blipurls","depth":4},{"value":"devices","id":"devices","depth":4},{"value":"dropdown","id":"dropdown","depth":4},{"value":"unsupported","id":"unsupported","depth":4},{"value":"working","id":"working","depth":4},{"value":"State relating to application updates","id":"state-relating-to-application-updates","depth":3},{"value":"electronUpdateManualChecked","id":"electronupdatemanualchecked","depth":4},{"value":"electronUpdateAvailableDismissed","id":"electronupdateavailabledismissed","depth":4},{"value":"electronUpdateAvailable","id":"electronupdateavailable","depth":4},{"value":"electronUpdateDownloaded","id":"electronupdatedownloaded","depth":4}],"frontmatter":{"seo":{"title":"State Tree Glossary"}},"lastModified":"2026-05-28T16:33:56.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/uploader/state/statetreeglossary","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}