From cfcb6d398250005427c77a560d87e3a7c67717ef Mon Sep 17 00:00:00 2001 From: Piotr Mitros Date: Tue, 28 Feb 2023 22:47:02 -0500 Subject: [PATCH] Better code documentation --- package.json | 2 +- src/lib/components/LOConnection.react.js | 62 ++++++++++++++++++- src/lib/components/LOIndicatorBars.react.js | 23 +++++-- src/lib/components/LOMetrics.react.js | 21 +++++-- src/lib/components/LOTextHighlight.react.js | 17 +++-- .../components/StudentOverviewCard.react.js | 14 +++-- 6 files changed, 117 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index b47eb42..c877865 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "build:activated": "npm run build:js && npm run build:backends-activated" }, "author": "Bradley Erickson ", - "license": "GPL-3.0", + "license": "AGPL-3.0", "dependencies": { "bootstrap": "^5.2.0", "ramda": "^0.26.1", diff --git a/src/lib/components/LOConnection.react.js b/src/lib/components/LOConnection.react.js index 8bd44f6..5f2b8cb 100644 --- a/src/lib/components/LOConnection.react.js +++ b/src/lib/components/LOConnection.react.js @@ -2,10 +2,24 @@ import {Component} from 'react'; import PropTypes from 'prop-types'; /** - * A simple interface to + * LOConnection is a simple interface to the Learning Observer (LO) + * WebSocket API. + * + * LOConnection is designed to act as a bridge, enabling users to + * write dashboards using the Dash and Plotly libraries within + * LO. This component takes in several props, including the websocket + * endpoint URL, a data_scope dictionary, and a setProps callback + * function that should be called to report property changes to Dash. + * Once mounted, LOConnection listens for events, including onopen, + * onmessage, onerror, and onclose, and updates the state and message + * props accordingly. The component also includes an + * encode_query_string function, which is used to create a query + * string from a dictionary. + * + * We are planning to evolve this into a more complete protocol. That's + * still in progress. */ export default class LOConnection extends Component { - encode_query_string(obj) { /* Create a query string from a dictionary @@ -22,6 +36,23 @@ export default class LOConnection extends Component { return str.join("&"); } + /* Initialize a new WebSocket client. + + This function creates a new WebSocket client and sets up event + listeners for it. The URL of the WebSocket server is determined + by the `url` prop, or, if not provided, it is constructed using + the current location and query string parameters. + + Parameters: + - None + + Returns: + - None + + Side effects: + - Creates a new WebSocket client and sets up event listeners for it. + - Updates the component's props with information about the WebSocket connection state, incoming messages, and errors. + */ _init_client() { // Create a new client. let {url} = this.props; @@ -80,15 +111,40 @@ export default class LOConnection extends Component { }) } } - + + /* Initialize the component. + + For now, Initializes a WebSocket client and sets up event + listeners for various WebSocket events, via _init_client. This + method is called after the component is mounted (i.e., inserted + into the DOM). + */ componentDidMount() { this._init_client() } + /* React/Dash lifecycle method called after a component updates + (e.g. a new message is inserted). It is used here to send + messages and re-initialize the WebSocket client when the + component's props change. + + Args: + - prevProps: the previous props of the component. + + Sends messages: + - If the 'send' prop is truthy and different from its previous value, and the WebSocket + connection is open, the 'send' prop is sent as a message through the WebSocket client. + + Re-initializes the WebSocket client: + - If the 'data_scope' prop has changed from its previous value, the WebSocket connection + is closed and re-initialized with the new 'data_scope' value by calling '_init_client'. + */ componentDidUpdate(prevProps) { const {send, data_scope} = this.props; // Send messages. if (send && send !== prevProps.send) { + // Check if the WebSocket is open before sending the message. If not, we'll get called + // again when props change when it opens. if (this.props.state.readyState === WebSocket.OPEN) { this.client.send(send) } diff --git a/src/lib/components/LOIndicatorBars.react.js b/src/lib/components/LOIndicatorBars.react.js index efe18f1..02544af 100644 --- a/src/lib/components/LOIndicatorBars.react.js +++ b/src/lib/components/LOIndicatorBars.react.js @@ -4,10 +4,25 @@ import ProgressBar from 'react-bootstrap/ProgressBar'; /** * LOIndicatorBars provide progress bars. - * It takes a property, `data`, and - * outputs each item as a label/progress bar pair. - * If the id of the item is not in the property `shown`, - * it will not appear. + * + * A React component that renders a set of indicator bars, each showing a label, a value, and a help text. + * The component expects the following props: + * - id (string): the HTML id of the top-level element. + * - setProps (function): a function to update the component props. + * - data (object): a dictionary of indicators, where each key is an indicator ID and each value is an object + * with the following keys: + * - id (string): the indicator ID. + * - label (string): the label to show before the indicator bar. + * - value (number): the value of the indicator bar (between 0 and 100). + * - help (string): a help text to show when hovering over the indicator bar. + * - shown (array): an array of indicator IDs that should be shown (all other indicators will be hidden). + * - class_name (string): a CSS class name to add to the top-level element. + * + * The component renders a `div` element with the specified id and class name, and a set of child `div` elements, + * each representing an indicator bar. The bars are sorted in the order of their keys in the `data` prop. Each bar + * shows the label and a progress bar with the value and help text. The progress bar color is based on the value + * (red for values below 34, yellow for values between 34 and 67, and green for values above 67). The bars are + * hidden or shown based on the `shown` prop. */ export default class LOIndicatorBars extends Component { diff --git a/src/lib/components/LOMetrics.react.js b/src/lib/components/LOMetrics.react.js index 20aba26..4aec7f4 100644 --- a/src/lib/components/LOMetrics.react.js +++ b/src/lib/components/LOMetrics.react.js @@ -3,11 +3,22 @@ import PropTypes from 'prop-types'; import Badge from 'react-bootstrap/Badge'; /** - * LOMetrics creates badges for numeric values. - * It takes a property, `data`, and - * outputs each item as a badge. - * If the id of the item is not in the property `shown`, - * it will not appear. + * A React / dash / LO component that creates badges for numeric + * values. It takes a set of properties and outputs each item as a + * badge. If the ID of the item is not in the property `shown`, it + * will not appear. + * + * @param {string} id - The ID of the component. + * @param {function} setProps - A function that can be called to set the properties of the component. + * @param {Object} data - An object containing the data to be displayed as badges. The keys are the IDs of the metrics + * and the values are objects containing the following properties: + * - value: the numeric value of the metric + * - label: a label to be displayed next to the value + * - help: (optional) additional information to be displayed as a tooltip + * @param {Array} shown - An array of metric IDs to be displayed as badges. + * @param {string} class_name - An optional CSS class to be added to the component. + * + * @returns {ReactNode} A React component that displays the metrics as badges. */ export default class LOMetrics extends Component { diff --git a/src/lib/components/LOTextHighlight.react.js b/src/lib/components/LOTextHighlight.react.js index 4fe31b1..f3bc1eb 100644 --- a/src/lib/components/LOTextHighlight.react.js +++ b/src/lib/components/LOTextHighlight.react.js @@ -2,10 +2,19 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; /** - * LOTextHighlight provides breakpoints and classes to allow for later highlighting. - * It takes a property, `text`, and - * and breaks it up based on all possible breakpoints in property `highlight_breakpoints`. - * The text is output as a variety of spans with classnames corresponding to ids. + * LOTextHighlight provides breakpoints and classes to allow for later + * highlighting. It takes a property, `text`, and and breaks it up + * based on all possible breakpoints in property + * `highlight_breakpoints`. The text is output as a variety of spans + * with classnames corresponding to ids. + * + * @param {string} text - The text to be highlighted + * @param {Object} highlight_breakpoints - An object specifying the breakpoints for highlighting. The keys should be unique IDs and the values should be objects with the following properties: + * - `id`: The unique ID for this set of highlight breakpoints + * - `value`: An array of `[start, length]` tuples specifying the start index and length of each highlight. The tuples should be sorted in ascending order by start index. + * - `label` (optional): A label to be used in combination with the highlight ID for customizing styling. + * @param {string} [class_name] - Additional class name(s) to apply to the rendered component + * @param {string} [id] - ID to apply to the rendered component */ export default class LOTextHighlight extends Component { diff --git a/src/lib/components/StudentOverviewCard.react.js b/src/lib/components/StudentOverviewCard.react.js index eeb11da..35c9dab 100644 --- a/src/lib/components/StudentOverviewCard.react.js +++ b/src/lib/components/StudentOverviewCard.react.js @@ -9,11 +9,15 @@ import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; /** - * ExampleComponent is an example component. - * It takes a property, `label`, and - * displays it. - * It renders an input with the property `value` - * which is editable by the user. + * StudentOverviewCard + * + * This is the main card for a student in the Writing Observer dashboard. + * + * The key parameter passed in is data. + * + * - data.metrics variable generates a badge component for each metric object. + * - data.indicators generates a progress-style bar for each indicator object. + * - data.highlights variable is used to determine which parts of the student's text should be highlighted */ export default class StudentOverviewCard extends Component {