- AuthForm
AuthForm is a wrapper component that switches between LoginForm and Signup Form It can be primed with a default via the initialMode prop.
- Browser
Browser is a drop-down menu embedded in Nav that lets the user jump to any level or island that they have beaten in the past
- Checkpoint
Checkpoint is a one-time pop-up that asks the user to fill in his or her school/location Originally intended to be a more generic "Checkpoint" system that would support arbitrary banners/messages, it is currently only used for gathering school info
- CodeBlockCard
CodeBlockCards appear throughout the site as a way of previewing a student's codeblock It contains both the small clickable card with preview image AND the dialog box that pops up over the page and shows the full screen code editor.
- CodeBlockEditor
CodeBlockEditor is the popover that comes up for the final test of an island. It is mostly a wrapper around CodeEditor that provides the student with the test prompt, cheat sheet, and db routes to save their progress when they pass the test
- CodeBlockList
CodeBlockList is used by Projects to display codeblocks to draw inspiration from.
- CodeEditor
CodeEditor is a two-panel rendering component for student code. It uses AceEditor for the student panel (left), and a remote rendering iframe for the page preview (right).
- DrawerValidation
The CodeEditor is responsible for handling violation of the rules set out for a given programming challenge. A list of errors is passed in as a prop - this component is responsible for creating a readable sentence form of what is wrong with the student's code. For example, "Your HTML code is missing an
- CollabList
Provides a list of Collaborators for a project provided by props.
- CollabSearch
Popover window so that project owners can find and add new users to collaborate on a given project
- Comment
Comments belong to Threads. Note that there is no text editor here - all posting is handled by Thread.jsx. This component is for displaying only.
- ContestSignup
Signup page for (currently postponed) project contest. Signing up simply enters the user in the contest, users still must go to the ContestSubmit page to select a project and finalize the procedure.
- ContestSubmit
User selects a project for the contest and submits their entry.
- CTA
Call To Action Component, encourage users to sign up after visiting SEO-enable page
- Discussion
Discussion Board wraps a list of threads (which in turn hosts a list of comments). Discussion boards currently only apply to slides, but they are designed to be able to apply to anything (projects, codeblocks, etc)
- IslandLink
IslandLink is the zoomed-out picture of the island used in the overworld map, lesson plan, etc
- Loading
Loading is explicitly used by CANON itself for any page that has canon "needs", which is why this is a full container page with . The LoadingSpinner component was separated out for embedded use (no clouds)
- LoadingSpinner
Loading spinner for a huge number of components in Codelife, mostly used in render cycles while waiting for axios to return with data
- LoginForm
Works alongside SignUpForm to log users in. Essentially a wrapper for the canon "login" action
- Nav
Nav Component is the header of the page - containing login controls and the Island Browser
- PasswordReset
Wrapper Component for the reset password dispatch action of canon
- ProjectCard
ProjectCard, similar to CodeBlockCard, is a small visual container with a Dialog popover to showcase projects. It is used on the Homepage as well as in User Profiles to list their projects
- ReportBox
ReportBox is a reusable component for reporting threads, comments, projects, and codeblocks for inappropriate content. As with many data structures in codelife, it uses a SINGLE reports table, with a "type" column that designates which table the report_id refers to.
- Search
The Search component is embedded in Nav and is used to search users and projects. It utilizes postgres trigrams serverside (see readme)
- SelectGeo
Component for selecting a location from a database of geo codes in Brazil
- SelectSchool
Component for choosing a school from a db of school ids and geos - meant to be used in conjunction with SelectGeo
- ShareDirectLink
Popover Component for sharing a link to a students project/codeblock. Copies url to clipboard.
- ShareFacebookLink
Component for sharing facebook links. Due to the fact that xvfb screenshots require a few seconds to render, this component receives a "screenshotReady" prop from the embedding component, which waits a few seconds to ensure that Facebook's FIRST capture of the page has the finished screenshot
- SignupForm
Sister component to AuthForm, this component wraps the Canon "signup" action and does appropriate error checking
- InputCode
InputCode is a slide type that requires the student to complete a coding test The CodeEditor component is embedded with a series of rules, and the slide will not unblock until the student submits a passing code section. It is mostly a wrapper for CodeEditor, with some controls to execute controls or unblock a slide.
- Quiz
Quiz is a blocking multiple-choice question, powered by the quizjson column in the slides db
- RenderCode
RenderCode is similar to InputCode, but the CodeEditor is in readonly mode For showing code examples with explanations.
- TextImage
TextImage is text left, image right. Images are stored in /slide_images/{id}.jpg Images are uploaded through the CMS and a translated version is chosen here via locales
- Thread
A thread is the top-level child of a Discussion. Discussions have many threads, threads have many comments.
- UserCard
UserCard is a component used on a profile page to display other users that share the logged in user's school or location
- About
About page - contains translated about text and a simple photoslide component from Datawheel's first visit to Minas
- Contest
Contest Component handles the (currently postponed) contest, including all the steps and checks to ensure eligibility. Page is public-facing (doesn't require login) to gain attention - the first step is creating an account
- Glossary
The Glossary component retrieves words It is worth noting that the storage of glossary words is somewhat split-brained. Here in Glossary.jsx, canon's "need" functionality is used to ensure that words are rendered server-side and therefore indexable by search engines. However, glossary words used to live in the Redux Store (and in QuillWrapper, this is still how they are loaded). Both places use the same API endpoint - but one uses canon needs, the other puts the data into redux in App.jsx's mount method.
- Home
Homepage component - mostly a wrapper for other smaller components (cards, features, etc)
- Level
Main Level-viewing component (e.g., Jungle Island). It shows a list of the levels available as well as the ending codeblock test. Codeblocks by other users are listed underneath the island
- Island
Displays all available islands
- Leaderboard
Leaderboard is a sortable table that lists users by their in-game progress.
- LearnMore
Simple partners page to link to other online coding projects
- LessonPlan
A public-facing listing of all slides and quizzes, to be used by teachers as a lesson plan, students as a reference guide, and to aid in directing users to the site via search engines. Lesson plan uses Canon's "Needs" to render the page serverside, so that the page is indexable by SEO bots
- Profile
Class component for a user profile. This is a public page and meant to be shared. If a user is logged in AND this is their profile, show an edit button allowing them to edit it.
- UserCodeBlocks
Class component for displaying lists of user's snippets. This is shown on the public profile for a user and requires sending 1 prop: a ref to the user
- UserProjects
Class component for displaying lists of user's projects. This is shown on the public profile for a user and requires sending 1 prop: a ref to the user
- UsersList
Class component for displaying lists of user's snippets. This is shown on the public profile for a user and requires sending 1 prop: a ref to the user
- Projects
Projects is one of the largest Pages in codelife - It is responsible for all CRUD operations of projects, processing screenshots, and listing user codeblocks for inspiration. Longer term, this should be refactored into smaller components.
- ResetPw
Very small wrapper class for PasswordReset Component
- Share
The Share Page is a top-level page that does not require login, enabling users to share their projects or codeblocks on facebook or with others. It looks up the content via name/user and renders a fullscreen codeeditor for display, essentially acting as a hosting page for the students' work. Show a Report bar on the bottom for logged in users to report inappropriate content
- Slide
The slide component is the wrapper for all the various slidetypes in Codelife. However, it interacts a great deal with the db and greater site, as reaching the last slide updates user progress, and each slide has a Discussion board beneath it. It's important to note that currently a Level must be beaten all at once - the "latestSlideCompleted" variable in state is not persisted anywhere, and leaving the lesson does not restart the user halfway through a level. Longer term, more granular tracking of user location would be a nice enhancement.
- Splash
Simple splash page that lists about text for the Codelife Project
- Survey
Completed/Deprecated Survey Module from a 2017 Survey that followed a beta test in Minas Gerais. Consists of Radio buttons and a DB post.
- threadInclude
threadsRoute is used for retrieving threads and their associated comments. Unlike islands, likes, and many of the other earlier data structures in development, threads make better use of Sequelize associations, implicitly including comments in the thread payloads they belong to. This is distinctly different from islands/levels/slides, which get entire lists from the tables and then compile them client side. Going forward, the hierarchical/sequelize-association method of delivering API data (without flattening) is the more correct one. Threads have entity_ids and types. Currently the only two types are comments and threads, however the intention was that discussions could expand to encompass projects/codeblocks or more
- cvMatch
Given a rule and a block of code, check the Javascript and perform an exact match check on the regex. Used for things like "code must contain getElementById"
- cvNests
Given a rule and a block of code, check that a given tag is nested inside another tag. Used for things like "html nests body." Note that this does not currently account for subsequent occurences (only checks for first occurences)
- cvUses
Given a rule and a block of code, use a hard-coded regex to check for a SPECIFIC pattern. Example include a for block "for (;;) {}", ifelse "if () {} else {}" or a generic invocation of a function "functionName(){}"
- attrCount
Given a needle (like h1), an attribute (like color), a value (like red), and a JSON representation of the code as prepared by himalaya (HTML parser), recursively climb down the nested json tree, testing at each node for the presence of the needle, and if provided, whether that node has an attribute, and, if provided, whether that attribute's value exactly matches the provided value.
- cvContainsSelfClosingTag
Given a rule and a block of code, search for a self closing tag such as Optionally run attrCount to check for extra rules (such as requiring "src")
- cvContainsOne
Given a rule and a block of code, ensure that the given needle (such as ) occurs once and only once in the code (useful for tags like body, head, html)
- cvContainsTag
Given a rule and a block of code, check if a given tag (such as
) is included in the code. Optionally, use attrCount to match any provided attributes or values in the rule.
- cvContainsStyle
Given a rule and a block of code, using the "css" module to turn the css into a crawlable object. Fold over that generated parsed object and drill down to check if the rule's property matches the property and value of the css entered by the student.
- flattenCodeBlock(user, cb) ⇒
Object
Given the logged-in user and a codeblock, this function "flattens" the object by reaching into the associated tables queries (such as reports and likes) and bubbling them up to a top-level prop This type of function is really only used here and in projectsRoute. As codelife development progressed, the pattern shifted more to expect the nested nature of sequelize queries, meaning flattening wasn't necessary.
- strip()
This route is specifically for the canon "needs" version of the glossary It has a lang switch because the glossary needs to be rendered server side for SEO optimization.
- flattenProfile(user, p)
Similar to codeblocksroute, earlier in the project a lot of work was done to keep the payloads returned by APIs as flat objects. Later routes trended more towards trusting sequelize to form the hierarchy via associations. This helper function bubbles up associations into top-level properties.
- flattenProject(user, p) ⇒
Object
Given the logged-in user and a project, this function "flattens" the object by reaching into the associated tables queries (such as reports and likes) and bubbling them up to a top-level prop This type of function is really only used here and in codeblocksroute. As codelife development progressed, the pattern shifted more to expect the nested nature of sequelize queries, meaning flattening wasn't necessary.
- pruneThread(user, t) ⇒
Object
Given a user and a thread, prepare the thread to be returned to the requester. This involves a number of operations, including collating likes and reports, rewriting banned content, and deleting certain sensitive keys so they don't leak out through the API
AuthForm is a wrapper component that switches between LoginForm and Signup Form It can be primed with a default via the initialMode prop.
Kind: global class
Browser is a drop-down menu embedded in Nav that lets the user jump to any level or island that they have beaten in the past
Kind: global class
On mount, fetch all islands/levels/slides, sort them, and arrange them hierarchically for use in the Blueprint Tree. Also grab the logged in user's progress so that the browser can lock unbeaten levels.
Kind: instance method of Browser
Builds the "nodes" object that will be used to populate the blueprint tree. The Blueprint Tree component requires lots of metadata and nesting, so a fair amount of crawling must be done to populate it properly Note: This is borrowed heavily from the tree in the CMS. Someday they should be merged
Kind: instance method of Browser
Given a blueprint tree node, saved during the buildTree function, expand and select the appropriate node to match the location
Kind: instance method of Browser
Param | Type | Description |
---|---|---|
nodeFromProps | Object |
A Blueprint Tree node |
Helper function to avoid errors from accessing non-existent properties Longer term, database defaults values should be established to avoid this
Kind: instance method of Browser
Returns: Object
- an object whose null/undefined params are changed to ""
Param | Type | Description |
---|---|---|
obj | Object |
the object to prune |
As the user beats new levels, they are written to the db, but no redux-level store is updated. This public-facing function is invoked by Nav.jsx when the Browser is opened, resulting in a short loading screen while the latest progress is retrieved. See Nav.jsx for more details.
Kind: instance method of Browser
Similar to initNodeFromProps which expands the Blueprint Tree, this function selects the node that matches the LinkObj provided by Nav.
Kind: instance method of Browser
Callback for clicking a node. Uses browserhistory to navigate the user to the new page
Kind: instance method of Browser
Param | Type | Description |
---|---|---|
node | Object |
The blueprint node that was clicked |
Checkpoint is a one-time pop-up that asks the user to fill in his or her school/location Originally intended to be a more generic "Checkpoint" system that would support arbitrary banners/messages, it is currently only used for gathering school info
Kind: global class
CodeBlockCards appear throughout the site as a way of previewing a student's codeblock It contains both the small clickable card with preview image AND the dialog box that pops up over the page and shows the full screen code editor.
Kind: global class
Write the current like status of this codeblock to the db. CodeBlockList must be informed when this happens so it can reorder the codeblocks (liked codeblocks come first) so props.reportLike on return.
Kind: instance method of CodeBlockCard
Admin-only button callback that pings an API route to manually generate a screenshot for this codeblock (usually only happens when codeblock owner saves file)
Kind: instance method of CodeBlockCard
When the forking sub-menu is opened, highlight and select the text for easy editing
Kind: instance method of CodeBlockCard
Admin-only button callback that sets a codeblock as featured or not (featured codeblocks show up on the homepage)
Kind: instance method of CodeBlockCard
Codeblocks can be forked into projects, so students may remix another student's work. This function creates that new project and populates it with the codeblock data
Kind: instance method of CodeBlockCard
Switch that functions a like on and off. Note that this is front-end only and does not update the backend.
Kind: instance method of CodeBlockCard
Toggles the like visually (toggleLike) and saves it to the db (saveLikeStatus)
Kind: instance method of CodeBlockCard
On mount, grab the codeblock from props and create a unique placeholder fork name via epoch time
Kind: instance method of CodeBlockCard
On Update, if new props have been loaded in, load the new codeblock into state and update fork title
Kind: instance method of CodeBlockCard
This method is passed down as a callback to ReportBox. When reportBox signals a report, it calls this function, which updates the embedded codeblock itself and forces a refresh
Kind: instance method of CodeBlockCard
CodeBlockEditor is the popover that comes up for the final test of an island. It is mostly a wrapper around CodeEditor that provides the student with the test prompt, cheat sheet, and db routes to save their progress when they pass the test
Kind: global class
On Mount, parse various props passed down and add them to state.
Kind: instance method of CodeBlockEditor
When a user passes a codeblock for the first time, the parent Island component must be informed so it can close the popover and show a the "next island" dialog. Pass this callback down to codeeditor to enable that
Kind: instance method of CodeBlockEditor
Callback passed to CodeEditor so that CodeEditor can report when the user is using a script tag (therefore show an execute button in here in CodeBlockEditor)
Kind: instance method of CodeBlockEditor
Write progress to db when codeblock is passed
Kind: instance method of CodeBlockEditor
Callback passed down to the CodeEditor, allowing this parent component to respond to text changes if desired.
Kind: instance method of CodeBlockEditor
Set codeblock back to original test prompt state
Kind: instance method of CodeBlockEditor
Show popup warning (Are you sure?)
Kind: instance method of CodeBlockEditor
Show popup warning (Are you sure?)
Kind: instance method of CodeBlockEditor
Change codeblock name in place. Note that this doesn't save it to the db yet
Kind: instance method of CodeBlockEditor
Intermediary function that blocks some editing functions until the save is complete This gets around a known bug where clicking save twice can write two copies to the db
Kind: instance method of CodeBlockEditor
When the user clicks save & submit, make sure the internal CodeEditor has verified that their code is passing. If so, write the codeblock and progress to the db, and update the in-state version to reflect the new code
Kind: instance method of CodeBlockEditor
CodeBlockList is used by Projects to display codeblocks to draw inspiration from.
Kind: global class
On Mount, fetch all codeblocks, sort them by island, then separate into liked, unliked, and "mine" (logged in user's) Also fetch user progress so that unbeaten island codeblocks show as greyed out
Kind: instance method of CodeBlockList
Because a like can occur in a nested component (in this case, CodeBlockCard), this container component needs a callback function that can rearrange the items that exist in state.
Kind: instance method of CodeBlockList
Codeblocks have the ability to "fork" into a new project. For most embeddings of CodeBlockCards, this is as simple as creating the new project and using browserHistory to navigate the user to that page. However, as the user is ALREADY ON the Projects page, a callback is required to tell the parent component (Projects.jsx) to make a new project and update itself accordingly
Kind: instance method of CodeBlockList
CodeEditor is a two-panel rendering component for student code. It uses AceEditor for the student panel (left), and a remote rendering iframe for the page preview (right).
Kind: global class
- CodeEditor
- .componentDidMount()
- .componentWillUnmount()
- .pingRemote()
- .componentDidUpdate()
- .getBaseRules() ⇒
Array
- .receiveMessage(event)
- .getTitleText(theText) ⇒
String
- .stripJS(json) ⇒
Array
- .checkForErrors()
- .writeToIFrame(theText)
- .hasJS(theText)
- .renderText(executeJS)
- .iFrameLoaded()
- .onChangeText(theText)
- .myCatch(e)
- .myLog()
- .evalType(value) ⇒
String
- .handlePost()
- .checkJVMState(needle, value)
- .reverse(s) ⇒
String
- .internalRender()
- .setEntireContents(theText)
- .getEntireContents() ⇒
String
- .isPassing() ⇒
Boolean
- .changesMade() ⇒
Boolean
- .setChangeStatus(changesMade)
- .executeCode()
- .toggleDrawer()
- .fullscreenEditorToggle()
When CodeEditor mounts, add an EventListener that listens for postMessage events from the sandbox. Also, initiate a ping that checks with the sandbox page until it is ready to render.
Kind: instance method of CodeEditor
Before CodeEditor unmounts, remove the EventListener that listens for postMessage events from the sandbox.
Kind: instance method of CodeEditor
On a set interval, ping the remote sandbox until we receive a postMessage indicating that it's ready.
Kind: instance method of CodeEditor
On update, detect the state change of hasJS to inform the parent component whether or not to show an "Execute" button. If the rules in the props have changed, the parent component has changed (e.g., changing slides), necessitating state change of rules. Additionally, if the code content in the props have changed, clear any execution timeouts and reset the editor state.
Kind: instance method of CodeEditor
Generates a base state of HTML rules that will always be true for a well-formed page.
Kind: instance method of CodeEditor
Returns: Array
- Array of basic HTML rules in JSON format
Listens for events from postMessage, generated by the embedded iframe sandbox on codelife.tech. If the message didn't come from codelife.tech, automatically return. If the message is a special wakeup message, clear the ping intervals and set the iframe as ready for use. For all other messages, forward them to the handlePost function.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
event | String |
A postMessage event. |
Given the current text in the editor, if the HTML has a properly formatted <title> field, extract and return it.
Kind: instance method of CodeEditor
Returns: String
- The extracted text between <title> and </title>
Param | Type | Description |
---|---|---|
theText | String |
The current text contents of the editor |
Given a parsed JSON representation of the current code, recursively find and remove the contents of anything between <script> tags. This is important because we re-render the page on each keystroke, so firing JavaScript executions for each key is not ideal. Save the stripped-out JS into state, so we can determine from its prescence there if we should show an execute button or not.
Kind: instance method of CodeEditor
Returns: Array
- A rebuilt (minus JavaScript) JSON object that himalaya can parse back into HTML.
Param | Type | Description |
---|---|---|
json | Object |
A JSON Representation of the current text, as parsed by the himalaya library |
Grabs the current editor text from state, and prepare an array of true/false tests to be applied to it. Based on the results of those testing rules, set state variables that provide completion % feedback to the student.
Kind: instance method of CodeEditor
Given the text currently in the editor, send a postMessage containing that source to the sandbox for rendering.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
theText | String |
The text to be rendered in the sandbox |
Given the text currently in the editor, determine if it has open and closing script tags.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
theText | String |
The current editor text |
Called explictly after state updates that change the text. Using the helper function stripJS, this function prepares the code to be shipped to the sandbox via writeToIFrame. If it is the first time we are rendering, such as in a slide example, execute the JavaScript after a short delay.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
executeJS | Boolean |
If set to true, this function will execute any included JavaScript after a short delay. |
Called after "awake" message is received from sandbox, indicating that the iFrame is loaded and ready for postMessage events. Fetches rule text from API. On completion, set the prop-given initial text in state and invoke the onChangeText callback, so any componenent that embeds CodeEdtior may subscribes to this callback may be notified that the text has changed.
Kind: instance method of CodeEditor
Callback for the embedded AceEditor component. Used to bubble up text change events to this object's state and to the parent.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
theText | String |
The current state of the text in the code editor. |
Invoked by handlePost when an error is caught by the sandbox. Concatenates the error message to the console.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
e | String |
The error string retrieved from the sandbox |
Invoked by handlePost when an log message is returned by the sandbox. Concatenates the log message to the console. Because console.log can take multiple comma-separated arguments, extract the list using Array.from(arguments)
Kind: instance method of CodeEditor
Helper function to determine argument type for syntax highlighting in emulated console.
Kind: instance method of CodeEditor
Returns: String
- A String representing the type of the provided object
Param | Type | Description |
---|---|---|
value | * |
Value of any type |
Called by receiveMessage when postMessage events arrive from the sandbox. The first argument will always be a type designator that describes the following arguments so they can be routed for processing. A type of "completed" means the JavaScript has completed execution in the remote sandbox and error checking can begin.
Kind: instance method of CodeEditor
Called by handlePost to process postMessage events of type "rule". Iterates over list of rules in state and sets each rule's passing state based on whether the given argument matches type and value restrictions.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
needle | String |
The keyword rulename this value belongs to, typically a variable or function name |
value | * |
The actual, remote-sandbox determined value to check against. |
Reverses a string. Used by internalRender() to assist with regex.
Kind: instance method of CodeEditor
Returns: String
- The reversed string
Param | Type | Description |
---|---|---|
s | String |
The string to be reversed |
One of the more complex functions in CodeLife, internalRender is invoked when an "execute code" button is pressed. This function is responsible for sending a specially prepared version of the student's source code to a remote sandbox for execution. The remote sandbox has an iFrame of its own, where the code is being injected. References to the "parent" of this iFrame refer to functions in the sandbox responsible for sending information back to Codelife.com via postMessage. To prepare the code for remote execution, several steps must be taken:
- replace console.log with parent.myPost("console"...) to intercept console statements.
- prepend JavaScript code with initialization functions that "zero out" any rule variables the student must set correctly.
- append JavaScript code with parent.myPost("rule"...) methods that send variable state back to Codelife.com
- further append JavaScript code with parent.myPost("completed"...) to indicate that the run has completed.
- take ALL of that code, wrap it into a string literal that eval()s the code and catches any runtime errors.
- take the student's current code and replace its JavaScript with the prepared JavaScript
- invoke writeToIFrame, which sends the entire payload to the remote sandbox for execution. The sandbox then injects the prepared code into the iFrame, which calls its parent functions, and reports back here via postMessage.
Kind: instance method of CodeEditor
Externally available method that components can use to set the contents of the Code Editor functionally (as opposed to via props)
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
theText | String |
The string to set as the editor contents. |
Externally available method that components can use to get the contents of the Code Editor functionally (as opposed to via props)
Kind: instance method of CodeEditor
Returns: String
- The current contents of the editor
Externally available method that components can use to fetch passing state
Kind: instance method of CodeEditor
Returns: Boolean
- Whether the code is in a passing state
Externally available method that components can use to determine whether the editor is "dirty," i.e., changes made that require saving
Kind: instance method of CodeEditor
Returns: Boolean
- Whether changes have been made to the code since its initial state or last save
Externally available method that components can use to set the editor as "dirty/clean" i.e., changes made. This is a necessary callback for operations like Saving Content - embedding components need to set changesMade to false.
Kind: instance method of CodeEditor
Param | Type | Description |
---|---|---|
changesMade | Boolean |
Boolean value to set "dirty/clean" status in editor. |
Externally available method that components can use to execute the JavaScript contents of the editor.
Kind: instance method of CodeEditor
Externally available method that components can use to set drawer visibility state.
Kind: instance method of CodeEditor
toggle fullscreen state
Kind: instance method of CodeEditor
The CodeEditor is responsible for handling violation of the rules set out for a given programming challenge. A list of errors is passed in as a prop - this component is responsible for creating a readable sentence form of what is wrong with the student's code. For example, "Your HTML code is missing an
tag". The format of this language is stored in the database as "Your {{p1}} is missing {{p2}}." (Note that this need be translated by lang)
Kind: global class
Provides a list of Collaborators for a project provided by props.
Kind: global class
Popover window so that project owners can find and add new users to collaborate on a given project
Kind: global class
Don't start hitting the database until the query is more than 2 characters long
Kind: instance method of CollabSearch
Given a clicked collaborator, if the constraints are met, post it to userprofiles_profiles (collab table)
Kind: instance method of CollabSearch
Given a uid and the pid of the current project, remove the matching row from userprofiles_profiles
Kind: instance method of CollabSearch
Comments belong to Threads. Note that there is no text editor here - all posting is handled by Thread.jsx. This component is for displaying only.
Kind: global class
The comment itself is passed in via props. Put it in state
Kind: instance method of Comment
Handle Liking and Unliking of comments
Kind: instance method of Comment
When the nested ReportBox component processes a report, This commment module needs to update the button to reflect the new state. This callback handles that.
Kind: instance method of Comment
Signup page for (currently postponed) project contest. Signing up simply enters the user in the contest, users still must go to the ContestSubmit page to select a project and finalize the procedure.
Kind: global class
On Mount, fetch the profile of the logged in user.
Kind: instance method of ContestSignup
Formatting rules for Cadastro de Pessoas Físicas
Kind: instance method of ContestSignup
Onclick handler that prepares entry payloads to various endpoints. Note that setting school id/ geo id in this contest entry page also updates the actual profile of the user.
Kind: instance method of ContestSignup
User selects a project for the contest and submits their entry.
Kind: global class
On Mount, fetch all the projects of the currently logged-in user, as well as their entry status
Kind: instance method of ContestSubmit
On Click, prepare contest payload and post it to the endpoint
Kind: instance method of ContestSubmit
Call To Action Component, encourage users to sign up after visiting SEO-enable page
Kind: global class
Discussion Board wraps a list of threads (which in turn hosts a list of comments). Discussion boards currently only apply to slides, but they are designed to be able to apply to anything (projects, codeblocks, etc)
Kind: global class
When the user changes slides, hit the API endpoind and fetch the new thread data
Kind: instance method of Discussion
Prepare payload and post a new thread to the db
Kind: instance method of Discussion
On sort selection, sort the threads in state
Kind: instance method of Discussion
IslandLink is the zoomed-out picture of the island used in the overworld map, lesson plan, etc
Kind: global class
Loading is explicitly used by CANON itself for any page that has canon "needs", which is why this is a full container page with . The LoadingSpinner component was separated out for embedded use (no clouds)
Kind: global class
Loading spinner for a huge number of components in Codelife, mostly used in render cycles while waiting for axios to return with data
Kind: global class
Works alongside SignUpForm to log users in. Essentially a wrapper for the canon "login" action
Kind: global class
The login dispatch is mapped to props and called here
Kind: instance method of LoginForm
Nav Component is the header of the page - containing login controls and the Island Browser
Kind: global class
When Nav Mounts, it is almost always because the page/app is being loaded from scratch, either because the user is visiting for the first time, OR a login has been attempted, and the result must be handled. As such, there is a fairly length decision tree here so that feedback can be shown.
Kind: instance method of Nav
When the user clicks an island/location in the embedded Browser component, they have chosen to navigate to a new page. This callback is needed so the Browser's wrapping component (this one) can hide the Browser.
Kind: instance method of Nav
Wrapper Component for the reset password dispatch action of canon
Kind: global class
On Mount, access the URL information from router and grab the token if it is there.
Kind: instance method of PasswordReset
Password field change handler, ensure passwords match before submitting dispatch
Kind: instance method of PasswordReset
Listen for changes to this.props.auth, and show a Toast message that reflects its state
Kind: instance method of PasswordReset
ProjectCard, similar to CodeBlockCard, is a small visual container with a Dialog popover to showcase projects. It is used on the Homepage as well as in User Profiles to list their projects
Kind: global class
Project Cards, though small visually, are responsible for containing and controlling their own Dialog Popover that shows the entirety of the project and its code
Kind: instance method of ProjectCard
Admin Only function to promote the given project to featured
Kind: instance method of ProjectCard
Admin only function to generate a screenshot for this project (usually so it can be featured on the homepage)
Kind: instance method of ProjectCard
Projects embed a ReportBox to allow for flagging. If a user uses that box to report the content, this callback notifies its parent (this component) that the project has been reported, so state can be updated
Kind: instance method of ProjectCard
ReportBox is a reusable component for reporting threads, comments, projects, and codeblocks for inappropriate content. As with many data structures in codelife, it uses a SINGLE reports table, with a "type" column that designates which table the report_id refers to.
Kind: global class
The Search component is embedded in Nav and is used to search users and projects. It utilizes postgres trigrams serverside (see readme)
Kind: global class
On keystroke, hit the search API endpoint
Kind: instance method of Search
Search is not a top-level component in routes.jsx, so it doesn't have access to the Router object that would indicate what page the user is on. This makes it difficult to collapse the search results if the user clicks a link outside the results. To get around this, a linkObj is passed down from App to Nav to here, and search is collapsed on URL change.
Kind: instance method of Search
onKeyDown is meant to capture inputs - but the arrow up/down aren't currently functional (user can use tabs and Enter key to go through links however). This UX could be improved.
Kind: instance method of Search
Send search query to API endpoint
Kind: instance method of Search
Component for selecting a location from a database of geo codes in Brazil
Kind: global class
On Mount, get the gid (embedded in props via userprofile) and populate the search bar accordingly
Kind: instance method of SelectGeo
Callback for the select box. Contains some code from what was going to be an "Unspecified" option, but was changed to a higher up "Rather not say" option in EditProfile.jsx which cancels out the dialog entirely and writes a hard-coded "-1" to the user's geo id.
Kind: instance method of SelectGeo
Component for choosing a school from a db of school ids and geos - meant to be used in conjunction with SelectGeo
Kind: global class
On Mount, get the sid from props (originally retrieved from userprofile) and populate the dropdown accordingly
Kind: instance method of SelectSchool
Callback for dual dropdown - Given a selected Geo, hit the API to retrieve all the schools for that Geo and populate the dropdown.
Kind: instance method of SelectSchool
Popover Component for sharing a link to a students project/codeblock. Copies url to clipboard.
Kind: global class
Component for sharing facebook links. Due to the fact that xvfb screenshots require a few seconds to render, this component receives a "screenshotReady" prop from the embedding component, which waits a few seconds to ensure that Facebook's FIRST capture of the page has the finished screenshot
Kind: global class
Sister component to AuthForm, this component wraps the Canon "signup" action and does appropriate error checking
Kind: global class
When the user clicks submit, verify some info before calling datawheel-canon's signup
action
Kind: instance method of SignupForm
InputCode is a slide type that requires the student to complete a coding test The CodeEditor component is embedded with a series of rules, and the slide will not unblock until the student submits a passing code section. It is mostly a wrapper for CodeEditor, with some controls to execute controls or unblock a slide.
Kind: global class
Retrieve the rules and starting code from props and put them into state
Kind: instance method of InputCode
If the user changes slides, update the rules
Kind: instance method of InputCode
The Embedded CodeEditor itself knows whether the student has written any javascript in the editor window. Dynamically show and hide an "execute" button based on this callback function
Kind: instance method of InputCode
Attempt to submit the current code state on click. Requires reaching into the wrapped CodeEditor instance itself to call a public function, isPassing, which is managed by the CodeEditor. If the student passes, inform the parent Slide component that this slide is unblocked and the student can continue
Kind: instance method of InputCode
Reset CodeEditor to original testing state, again by reaching into the CodeEditor instance itself and setting contents via a public method.
Kind: instance method of InputCode
Display Are you sure? Dialog
Kind: instance method of InputCode
Reach into the codeEditor and trigger javascript execution.
Kind: instance method of InputCode
Quiz is a blocking multiple-choice question, powered by the quizjson column in the slides db
Kind: global class
Callback for clicking an answer. Check ths JSON, and unblock the parent Slide if correct
Kind: instance method of Quiz
On Mount, populate the quiz prompt from props
Kind: instance method of Quiz
When the user changes slides, update the quizjson in state.
Kind: instance method of Quiz
RenderCode is similar to InputCode, but the CodeEditor is in readonly mode For showing code examples with explanations.
Kind: global class
Callback for CodeEditor, when it reports that the student is using javascript, show an exec button on this slide.
Kind: instance method of RenderCode
When the execute button is clicked, pass the command down to the public method in CodeEditor
Kind: instance method of RenderCode
TextImage is text left, image right. Images are stored in /slide_images/{id}.jpg Images are uploaded through the CMS and a translated version is chosen here via locales
Kind: global class
A thread is the top-level child of a Discussion. Discussions have many threads, threads have many comments.
Kind: global class
On Mount, retrieve the thread from props
Kind: instance method of Thread
A thread can only have one text window open at a time for a new comment to be added. Keep the details of this comment in state, and post it to the endpoint on submit
Kind: instance method of Thread
A report, handled by the sub-component ReportBox, uses this callback to tell Thread that the user has submitted a report
Kind: instance method of Thread
UserCard is a component used on a profile page to display other users that share the logged in user's school or location
Kind: global class
About page - contains translated about text and a simple photoslide component from Datawheel's first visit to Minas
Kind: global class
Contest Component handles the (currently postponed) contest, including all the steps and checks to ensure eligibility. Page is public-facing (doesn't require login) to gain attention - the first step is creating an account
Kind: global class
On mount, load the user, their progress, and their projects. Use this data to populate state and fill in the appropriate steps on the page
Kind: instance method of Contest
Signing up for the contest is a multi-step progress - use the state to determine where the user is so the boxes on the page can be checked accordingly.
Kind: instance method of Contest
The Glossary component retrieves words It is worth noting that the storage of glossary words is somewhat split-brained. Here in Glossary.jsx, canon's "need" functionality is used to ensure that words are rendered server-side and therefore indexable by search engines. However, glossary words used to live in the Redux Store (and in QuillWrapper, this is still how they are loaded). Both places use the same API endpoint - but one uses canon needs, the other puts the data into redux in App.jsx's mount method.
Kind: global class
Homepage component - mostly a wrapper for other smaller components (cards, features, etc)
Kind: global class
On mount, fetch the users progress so that a "continue your adventure" placard can be shown. Whether the user is logged or not, fetch the featured cb/projects
Kind: instance method of Home
Main Level-viewing component (e.g., Jungle Island). It shows a list of the levels available as well as the ending codeblock test. Codeblocks by other users are listed underneath the island
Kind: global class
- Level
- .loadFromDB()
- .maybeTriggerCodeblock()
- .componentDidUpdate()
- .componentDidMount()
- .componentWillUnmount()
- .toggleTest()
- .handleSave()
- .onFirstCompletion()
- .closeOverlay()
- .hasUserCompleted()
- .reportLike()
- .allLevelsBeaten()
- .promptFinalTest()
- .saveCheckpoint()
- .skipCheckpoint()
- .buildCheckpointPopover()
- .buildWinPopover()
- .buildTestPopover()
On Mount, or Update (meaning the user switched islands) Load the necessary progress/codeblock data from the db.
Kind: instance method of Level
The presence of /show
in the URL is a permalink to open the codeblock. Was originally intended so that codeblockcards could directly link
to a user's own codeblock and automatically open it, but this feature was postponed.
Kind: instance method of Level
When the user changes pages, flush the state and reload from the database
Kind: instance method of Level
The code to load from DB already exists in ComponentDidUpdate, this dedupes that logic by just manually calling update on mount.
Kind: instance method of Level
A timeout is registered on Codeblock completion to process the screenshot, ensuring that it is complete before allowing fb sharing. Clear this timeout if the user leaves the page
Kind: instance method of Level
Hide or Show the codeblock test popover. Adjust the URL accordingly
Kind: instance method of Level
Callback for CodeBlockEditor on save. The CodeBlockEditor passes its codeblock back out to Level so that its Codeblock can be set.
Kind: instance method of Level
Called when the user finishes an island for the first time. Calls a refresh on the data to unlock codeblocks, shows the victory message, and invites the user to the next island.
Kind: instance method of Level
Upon Closing the winning pop-up, send the player to the next island.
Kind: instance method of Level
Levels and Islands are mixed together in a single array - so this can be used to test if a user has beaten a level (e.g. hello-world) or an entire island (e.g. island-1).
Kind: instance method of Level
The codeblocks underneath the island need to be informed via a callback when they are liked or unliked, as this affects the sorting.
Kind: instance method of Level
Used to determine if the final test should be shown.
Kind: instance method of Level
If a user has beaten all the levels on this island, but has NOT created a codeblock yet, they are in the state were the codeblock need be prompted
Kind: instance method of Level
Checkpoint is a pop-up that appears after level 1, asking the user to share their school. This is the api callback to update their profile
Kind: instance method of Level
If the user elects not to provide their school, write a hard-coded -1 to their sid. This saves the "prefer not to answer" choice and prevents future popups.
Kind: instance method of Level
This was written early in the project, before the Component nesting of React was fully put to use. This method encapsulates the checkpoint popover - but this should obviously be moved to a component, not a method.
Kind: instance method of Level
This was written early in the project, before the Component nesting of React was fully put to use. This method encapsulates the "You Win" popover - but this should obviously be moved to a component, not a method.
Kind: instance method of Level
This was written early in the project, before the Component nesting of React was fully put to use. This method encapsulates the test popover - but this should obviously be moved to a component, not a method.
Kind: instance method of Level
Displays all available islands
Kind: global class
On mount, fetch the progress for the currently logged in user.
Kind: instance method of Island
On mount, fetch the progress for the currently logged in user.
Kind: instance method of Island
Returns: Boolean
- Returns a boolean whether or not the user has completed the provided island ID.
Param | Type | Description |
---|---|---|
milestone | String |
An island ID. |
Leaderboard is a sortable table that lists users by their in-game progress.
Kind: global class
On Mount, retrieve stats from the API, calculate what percentage of completion this refers to, given the state of currently released islands, and update state.
Kind: instance method of Leaderboard
On selection of a sorting property, sort the users accordingly
Kind: instance method of Leaderboard
Simple partners page to link to other online coding projects
Kind: global class
A public-facing listing of all slides and quizzes, to be used by teachers as a lesson plan, students as a reference guide, and to aid in directing users to the site via search engines. Lesson plan uses Canon's "Needs" to render the page serverside, so that the page is indexable by SEO bots
Kind: global class
Class component for a user profile. This is a public page and meant to be shared. If a user is logged in AND this is their profile, show an edit button allowing them to edit it.
Kind: global class
Creates the Profile component with its initial state.
Param | Type | Description |
---|---|---|
loading | boolean |
true by defaults gets flipped post AJAX. |
error | string |
Gets set if no username matches username URL param. |
profileUser | object |
Gets set to full user object from DB. |
Grabs username from URL param, makes AJAX call to server and sets error state (if no user is found) or profileUser (if one is).
Kind: instance method of Profile
3 render states: case (loading)
- show loading case (error)
- show error msg from server case (user found)
- user info
Kind: instance method of Profile
Class component for displaying lists of user's snippets. This is shown on the public profile for a user and requires sending 1 prop: a ref to the user
Kind: global class
Creates the UserSnippets component with initial state.
Param | Type | Description |
---|---|---|
loading | boolean |
true by defaults gets flipped post AJAX. |
snippets | array |
Gets set by AJAX call from DB call. |
Grabs user id from user prop, makes AJAX call to server and returns the list of snippets.
Kind: instance method of UserCodeBlocks
Class component for displaying lists of user's projects. This is shown on the public profile for a user and requires sending 1 prop: a ref to the user
Kind: global class
Creates the UserProjects component with initial state.
Param | Type | Description |
---|---|---|
loading | boolean |
true by defaults gets flipped post AJAX. |
projects | array |
Gets set by AJAX call from DB call. |
Grabs user id from user prop, makes AJAX call to server and returns the list of projects.
Kind: instance method of UserProjects
Class component for displaying lists of user's snippets. This is shown on the public profile for a user and requires sending 1 prop: a ref to the user
Kind: global class
Creates the UserSnippets component with initial state.
Param | Type | Description |
---|---|---|
loading | boolean |
true by defaults gets flipped post AJAX. |
snippets | array |
Gets set by AJAX call from DB call. |
Grabs user id from user prop, makes AJAX call to server and returns the list of snippets.
Kind: instance method of UsersList
Projects is one of the largest Pages in codelife - It is responsible for all CRUD operations of projects, processing screenshots, and listing user codeblocks for inspiration. Longer term, this should be refactored into smaller components.
Kind: global class
On Mount, retrieve all projects by the logged in user, as well as the projects by OTHER users with whom the logged in user is listed as a collaborator, and put these in state.
Kind: instance method of Projects
Given a project id, open the project itself by fetching it from the database and loading it into state. Set the URL so it continues to match the open project permalink
Kind: instance method of Projects
The embedded CodeEditor is the only component that knows if the user has used javascript in their project. When this changes in CodeEditor, it bubbles that up via this callback so that Projects can dynamically show and hide an "Execute Code" button
Kind: instance method of Projects
Callback for the create new project button. Trims the name of URL-breakers and whitespace, posts an empty project to the API endpoint, and refreshes the project list from that API payload so the Project List accurately reflects the new project collection. Update the URL when the project is finished opening.
Kind: instance method of Projects
Opens the popover to name the project (which eventually calles createNewProject)
Kind: instance method of Projects
Deprecated / unused function
Kind: instance method of Projects
The alerts in this component have two states, false, or "truthy," that is, leaveAlert=false means that the window closed, and setting leaveAlert to what you want the alert to say makes it truthy, and therefore open. This click callback is the "are you sure" dialogue for leaving a collaboration
Kind: instance method of Projects
Upon confirming that this user wants to leave a collab, remove that user from the collabs tabel. Additionally, filter it out in state. Either way, close the leaveAlert
Kind: instance method of Projects
Though users are normally invited to share new projects on facebook, they may elect to opt out and "never show this again" which needs to write to their userprofile
Kind: instance method of Projects
Delete a given project. The argument here is confusing - originally clicking delete would delete the project immediately. The addition of a deleteAlert (similar to leaveAlert) stores the project to be deleted in the deleteAlert.
Kind: instance method of Projects
When a user clicks a project, attempt to open it. Reach into the CodeEditor and check if changes have been made, and if so, block the opening attempt until they save.
Kind: instance method of Projects
Prepare a payload containing the filename, id, content, etc to be sent to the update api. If this is the first time the user is saving a project, offer to share it on Facebook. Note that this is one of the many places in Codelife where a 5 second timer is used to allow the screenshot time to process
Kind: instance method of Projects
Callback for closing the share window, save the users preference if they asked not to be asked again.
Kind: instance method of Projects
Reach into the CodeEditor and call the executeCode function. This requires manual execution - otherwise if the user was writing something like "alert()" then it would render every single keystroke
Kind: instance method of Projects
On most parts of the site, forking a codeblock is as easy as creating the project and navigating the user to that page. However, if a user forks a codeblock from HERE on the project page, a slightly different behavior is required
Kind: instance method of Projects
Rename a project. Set title editability to false temporarily and prune URL-breakers and leading/trailing whitespace from the new name. Write the project to the db and update state
Kind: instance method of Projects
Keyboard callbacks
Kind: instance method of Projects
Very small wrapper class for PasswordReset Component
Kind: global class
The Share Page is a top-level page that does not require login, enabling users to share their projects or codeblocks on facebook or with others. It looks up the content via name/user and renders a fullscreen codeeditor for display, essentially acting as a hosting page for the students' work. Show a Report bar on the bottom for logged in users to report inappropriate content
Kind: global class
In order to color the ReportBox Button appropriate, it needs to be known if the logged in user has reported this content. Fetch the reports to check.
Kind: instance method of Share
The ReportBox component needs a callback to tell this outer component that a report has been processed.
Kind: instance method of Share
The slide component is the wrapper for all the various slidetypes in Codelife. However, it interacts a great deal with the db and greater site, as reaching the last slide updates user progress, and each slide has a Discussion board beneath it. It's important to note that currently a Level must be beaten all at once - the "latestSlideCompleted" variable in state is not persisted anywhere, and leaving the lesson does not restart the user halfway through a level. Longer term, more granular tracking of user location would be a nice enhancement.
Kind: global class
InputCode and Quiz slides are "blockers" in that they do not allow progress until a correct answer is provided. This function is called when the user beats a slide.
Kind: instance method of Slide
When the user reaches the final slide, write the level to the userprogress table. If the user looks at the discussion board, this level is marked as "skipped", which ultimately does not count towards overall completion%. Completing the level without help marks the level as completed.
Kind: instance method of Slide
Slide.jsx handles all the transitions from slide to slide, so a lot of work need be done when the user changes slides. The simplest case is beating a single slide, but they also may have beaten this lesson (db write), reached a blocking slide, or be changing levels entirely
Kind: instance method of Slide
On mount, hit the DB and add the keyboard listener
Kind: instance method of Slide
Given the island / level / slide (lid, mlid, sid) from the URL params Fetch the slides and userprogress from the db and start from the first slides
Kind: instance method of Slide
Admin-only direct link to the CMS to edit a slide's content
Kind: instance method of Slide
When the user goes to the next level, push the new URL and hard-reload. This should be refactored to a more React-y state reset.
Kind: instance method of Slide
Show or hide the "show discussion" confirm/deny menu
Kind: instance method of Slide
Reveal or hide the discussion component.
Kind: instance method of Slide
When a Discussion board posts a new thread, Slide needs to know this has happened. This callback pushes the new thread onto the list so the "thread count" updates
Kind: instance method of Slide
Simple splash page that lists about text for the Codelife Project
Kind: global class
Completed/Deprecated Survey Module from a 2017 Survey that followed a beta test in Minas Gerais. Consists of Radio buttons and a DB post.
Kind: global class
Grabs username from URL param, makes AJAX call to server and sets error state (if no user is found) or overrides state (if one is).
Kind: instance method of Survey
threadsRoute is used for retrieving threads and their associated comments. Unlike islands, likes, and many of the other earlier data structures in development, threads make better use of Sequelize associations, implicitly including comments in the thread payloads they belong to. This is distinctly different from islands/levels/slides, which get entire lists from the tables and then compile them client side. Going forward, the hierarchical/sequelize-association method of delivering API data (without flattening) is the more correct one. Threads have entity_ids and types. Currently the only two types are comments and threads, however the intention was that discussions could expand to encompass projects/codeblocks or more
Kind: global constant
Given a rule and a block of code, check the Javascript and perform an exact match check on the regex. Used for things like "code must contain getElementById"
Kind: global constant
Given a rule and a block of code, check that a given tag is nested inside another tag. Used for things like "html nests body." Note that this does not currently account for subsequent occurences (only checks for first occurences)
Kind: global constant
Given a rule and a block of code, use a hard-coded regex to check for a SPECIFIC pattern. Example include a for block "for (;;) {}", ifelse "if () {} else {}" or a generic invocation of a function "functionName(){}"
Kind: global constant
Given a needle (like h1), an attribute (like color), a value (like red), and a JSON representation of the code as prepared by himalaya (HTML parser), recursively climb down the nested json tree, testing at each node for the presence of the needle, and if provided, whether that node has an attribute, and, if provided, whether that attribute's value exactly matches the provided value.
Kind: global constant
Given a rule and a block of code, search for a self closing tag such as Optionally run attrCount to check for extra rules (such as requiring "src")
Kind: global constant
Given a rule and a block of code, ensure that the given needle (such as ) occurs once and only once in the code (useful for tags like body, head, html)
Kind: global constant
Given a rule and a block of code, check if a given tag (such as
) is included in the code. Optionally, use attrCount to match any provided attributes or values in the rule.
Kind: global constant
Given a rule and a block of code, using the "css" module to turn the css into a crawlable object. Fold over that generated parsed object and drill down to check if the rule's property matches the property and value of the css entered by the student.
Kind: global constant
Given the logged-in user and a codeblock, this function "flattens" the object by reaching into the associated tables queries (such as reports and likes) and bubbling them up to a top-level prop This type of function is really only used here and in projectsRoute. As codelife development progressed, the pattern shifted more to expect the nested nature of sequelize queries, meaning flattening wasn't necessary.
Kind: global function
Returns: Object
- The "flattened" codeblock, ready to be returned to the requester
Param | Type | Description |
---|---|---|
user | string |
The currently logged in user, as specified by datawheel-canon |
cb | Object |
The codeblock to flatten |
This route is specifically for the canon "needs" version of the glossary It has a lang switch because the glossary needs to be rendered server side for SEO optimization.
Kind: global function
Similar to codeblocksroute, earlier in the project a lot of work was done to keep the payloads returned by APIs as flat objects. Later routes trended more towards trusting sequelize to form the hierarchy via associations. This helper function bubbles up associations into top-level properties.
Kind: global function
Param | Type | Description |
---|---|---|
user | Object |
The logged in user |
p | Object |
the profile to flatten |
Given the logged-in user and a project, this function "flattens" the object by reaching into the associated tables queries (such as reports and likes) and bubbling them up to a top-level prop This type of function is really only used here and in codeblocksroute. As codelife development progressed, the pattern shifted more to expect the nested nature of sequelize queries, meaning flattening wasn't necessary.
Kind: global function
Returns: Object
- The "flattened" project, ready to be returned to the requester
Param | Type | Description |
---|---|---|
user | string |
The currently logged in user, as specified by datawheel-canon |
p | Object |
The project to flatten |
Given a user and a thread, prepare the thread to be returned to the requester. This involves a number of operations, including collating likes and reports, rewriting banned content, and deleting certain sensitive keys so they don't leak out through the API
Kind: global function
Returns: Object
- the pruned thread
Param | Type | Description |
---|---|---|
user | Object |
The logged-in user |
t | Object |
the Thread to be pruned |