Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"build:activated": "npm run build:js && npm run build:backends-activated"
},
"author": "Bradley Erickson <bbwe24@gmail.com>",
"license": "GPL-3.0",
"license": "AGPL-3.0",
"dependencies": {
"bootstrap": "^5.2.0",
"ramda": "^0.26.1",
Expand Down
62 changes: 59 additions & 3 deletions src/lib/components/LOConnection.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the param and return info be included in this comment instead of a subsequent one? Also in whichever format we follow (see other comments)

* 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
Expand All @@ -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;
Expand Down Expand Up @@ -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)
}
Expand Down
23 changes: 19 additions & 4 deletions src/lib/components/LOIndicatorBars.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which format should we use for documentation? This or the @params used elsewhere.

* - 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 {

Expand Down
21 changes: 16 additions & 5 deletions src/lib/components/LOMetrics.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>} 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 {

Expand Down
17 changes: 13 additions & 4 deletions src/lib/components/LOTextHighlight.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing returns statement

export default class LOTextHighlight extends Component {

Expand Down
14 changes: 9 additions & 5 deletions src/lib/components/StudentOverviewCard.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This component is currently not being used. Changed to using the individual items instead for more modularization. I'd recommend just removing this file (that can wait until we do the migration of the code though)


/**
* 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 {

Expand Down