diff --git a/app.json b/app.json index f4264505..2997ce39 100644 --- a/app.json +++ b/app.json @@ -3,7 +3,7 @@ "description": "Internal dashboard for Unloop to help them build a pipeline from prison to tech.", "repository": "https://github.com/calblueprint/unloop", "scripts": { - "postdeploy": "bundle exec rails db:schema:load db:seed" + "postdeploy": "bundle exec rails db:seed" }, "env": { "SMTP_HOST": { diff --git a/app/assets/images/action_item_step_0.svg b/app/assets/images/action_item_step_0.svg new file mode 100644 index 00000000..4e614e78 --- /dev/null +++ b/app/assets/images/action_item_step_0.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/assets/images/action_item_step_1.svg b/app/assets/images/action_item_step_1.svg new file mode 100644 index 00000000..e1181f35 --- /dev/null +++ b/app/assets/images/action_item_step_1.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/assets/images/action_item_step_2.svg b/app/assets/images/action_item_step_2.svg new file mode 100644 index 00000000..fbef4d00 --- /dev/null +++ b/app/assets/images/action_item_step_2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/assets/images/error_mailbox.svg b/app/assets/images/error_mailbox.svg new file mode 100644 index 00000000..742bb64c --- /dev/null +++ b/app/assets/images/error_mailbox.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/load_mail.svg b/app/assets/images/load_mail.svg new file mode 100644 index 00000000..e7355cb0 --- /dev/null +++ b/app/assets/images/load_mail.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/success_mailbox.svg b/app/assets/images/success_mailbox.svg new file mode 100644 index 00000000..a3dc2dfd --- /dev/null +++ b/app/assets/images/success_mailbox.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/controllers/api/personal_questionnaires_controller.rb b/app/controllers/api/personal_questionnaires_controller.rb index 63f0186f..7a045b40 100644 --- a/app/controllers/api/personal_questionnaires_controller.rb +++ b/app/controllers/api/personal_questionnaires_controller.rb @@ -55,7 +55,7 @@ def sentry_helper(personal_questionnaire) def questionnaire_params questionnaire_params = params.require(:personal_questionnaire).permit(:participant_id, - :doc_status, + :DOC_status, :housing, :mental_health, :medical, @@ -63,7 +63,7 @@ def questionnaire_params :clothing, :significant_relationships, :support_systems, - :doc_regulations, + :DOC_regulations, :treatment, :triggers_and_prevention, :personal_needs, diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 7841b4af..56872c48 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -15,7 +15,10 @@ def dashboard "case_notes_count" => p.case_notes.length, "paperworks_count" => p.paperworks.length, "paperworks_completed" => p.paperworks.where(agree: true).length, - "questionnaire_status" => completed(p)} + "questionnaire_status" => completed(p), + "assignments_completed" => p.assignments.where(completed: true).length, + "assignments_count" => p.assignments.length, + } @participants_list.push(d) end authorize Staff diff --git a/app/controllers/studio_assessments_controller.rb b/app/controllers/studio_assessments_controller.rb index 1c2ce66c..f91ce7fb 100644 --- a/app/controllers/studio_assessments_controller.rb +++ b/app/controllers/studio_assessments_controller.rb @@ -4,7 +4,8 @@ class StudioAssessmentsController < ApplicationController # GET /studio_assessments # GET /studio_assessments.json def index - @studio_assessments = StudioAssessment.all + skip_policy_scope + @studio_assessments = authorize StudioAssessment.all @studio_list = [] @studio_assessments.each do |s| curr = { @@ -23,7 +24,7 @@ def index } @studio_list.push(curr) end - skip_policy_scope + end # GET /studio_assessments/1 diff --git a/app/javascript/components/ActionItemCard/index.js b/app/javascript/components/ActionItemCard/index.js index 32a07ff8..478a0598 100644 --- a/app/javascript/components/ActionItemCard/index.js +++ b/app/javascript/components/ActionItemCard/index.js @@ -20,9 +20,10 @@ function ActionItemCard({ category, selected, renderClose, + handleOpenModal, // Used by style file // eslint-disable-next-line no-unused-vars - lastEntry = false, + addBorderBottom, handleIconClick, removeActionItem, }) { @@ -33,7 +34,7 @@ function ActionItemCard({ ); const renderCloseIcon = () => ( - + ); @@ -48,11 +49,31 @@ function ActionItemCard({ ); + const renderEditButton = () => ( + + ); + + const renderViewMoreButton = () => ( + + ); + return ( - + - {' '} - {title}{' '} + {title} - + - {renderClose ? renderCloseIcon() : null} + + {renderClose ? renderCloseIcon() : null} + @@ -109,17 +131,14 @@ function ActionItemCard({ - {/* Commented out because it doesn't have functionality right now */} - {/* - - */} - {renderClose ? null : renderDeleteButton()} + + {renderClose ? renderEditButton() : renderDeleteButton()} + + {renderViewMoreButton()} @@ -134,9 +153,10 @@ ActionItemCard.propTypes = { category: PropTypes.string.isRequired, selected: PropTypes.bool.isRequired, renderClose: PropTypes.bool.isRequired, + handleOpenModal: PropTypes.func.isRequired, dueDate: PropTypes.string, handleIconClick: PropTypes.func, removeActionItem: PropTypes.func, - lastEntry: PropTypes.bool, + addBorderBottom: PropTypes.bool, }; export default withStyles(styles)(ActionItemCard); diff --git a/app/javascript/components/ActionItemCard/styles.js b/app/javascript/components/ActionItemCard/styles.js index 12f01dae..dda1a6f3 100644 --- a/app/javascript/components/ActionItemCard/styles.js +++ b/app/javascript/components/ActionItemCard/styles.js @@ -12,17 +12,17 @@ const styles = theme => ({ fontSize: '10px', width: '60px', textAlign: 'center', - paddingLeft: '8px', - paddingRight: '8px', }, cardStyle: { - width: '95%', + width: '100%', height: '140px', - padding: '0px', - margin: '0px 15px', - boxShadow: '0px 0px 0px 0px', - borderBottom: ({ lastEntry }) => - lastEntry ? '0px' : `.75px solid ${theme.palette.common.lightGrey}`, + padding: '8px', + margin: '10px 0px', + boxShadow: 'none', + backgroundColor: theme.palette.common.white, + borderRadius: theme.shape.borderRadius, + borderBottom: ({ addBorderBottom }) => + addBorderBottom ? `.75px solid ${theme.palette.common.lightGrey}` : '0px', }, descriptionStyle: { textOverflow: 'ellipsis', diff --git a/app/javascript/components/ActionItemCreationContainer/index.js b/app/javascript/components/ActionItemCreationContainer/index.js index d6cb48e0..84402fdd 100644 --- a/app/javascript/components/ActionItemCreationContainer/index.js +++ b/app/javascript/components/ActionItemCreationContainer/index.js @@ -31,6 +31,7 @@ function ActionItemCreationContainer({ createActionItem, deleteTemplate, setFile, + handleOpenModal, }) { const [creationSetting, setCreationSetting] = useState(Setting.SCRATCH); const [addToTemplates, setAddToTemplates] = useState(false); @@ -107,6 +108,7 @@ function ActionItemCreationContainer({ selectActionItemTemplate={selectActionItemTemplate} removeSelectedActionItem={removeSelectedActionItem} deleteTemplate={deleteTemplate} + handleOpenModal={handleOpenModal} /> )} @@ -131,6 +133,7 @@ ActionItemCreationContainer.propTypes = { setDueDate: PropTypes.func.isRequired, setCategory: PropTypes.func.isRequired, deleteTemplate: PropTypes.func.isRequired, + handleOpenModal: PropTypes.func.isRequired, }; export default withStyles(styles)(ActionItemCreationContainer); diff --git a/app/javascript/components/ActionItemCreationPage/index.js b/app/javascript/components/ActionItemCreationPage/index.js index ccc87a6e..95f2e5b4 100644 --- a/app/javascript/components/ActionItemCreationPage/index.js +++ b/app/javascript/components/ActionItemCreationPage/index.js @@ -9,13 +9,11 @@ import Snackbar from '@material-ui/core/Snackbar'; import SnackbarContent from '@material-ui/core/SnackbarContent'; import ActionItemCreationContainer from 'components/ActionItemCreationContainer'; import ActionItemSearchParticipants from 'components/ActionItemSearchParticipants'; +import LoadModal from 'components/LoadModal'; import ActionItemList from 'components/ActionItemList'; +import ViewMoreModal from 'components/ViewMoreModal'; +import ActionItemModal from 'components/ActionItemModal'; import ActionItemDisplayParticipants from 'components/ActionItemDisplayParticipants'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import Button from '@material-ui/core/Button'; import { apiPost, apiDelete } from 'utils/axios'; import * as Sentry from '@sentry/browser'; import styles from './styles'; @@ -36,6 +34,11 @@ class ActionItemCreationPage extends React.Component { selectedActionItems: [], submissionModal: false, file: null, + submissionStatus: null, + // State given to the view more and edit modals when invoked + modalActionItem: null, + viewMoreModalOpen: false, + editModalOpen: false, }; this.addUserToState = this.addUserToState.bind(this); @@ -54,6 +57,14 @@ class ActionItemCreationPage extends React.Component { this.handleFile = this.handleFile.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.checkActionItemsEqual = this.checkActionItemsEqual.bind(this); + this.handleCloseModal = this.handleCloseModal.bind(this); + this.handleOpenModal = this.handleOpenModal.bind(this); + this.editActionItem = this.editActionItem.bind(this); + this.reloadPage = this.reloadPage.bind(this); + } + + reloadPage() { + window.location.href = '/assignments'; } checkActionItemsEqual(actionItem1, actionItem2) { @@ -65,6 +76,54 @@ class ActionItemCreationPage extends React.Component { ); } + // Used to close both the edit and view more modals + handleCloseModal() { + this.setState({ + modalActionItem: null, + viewMoreModalOpen: false, + editModalOpen: false, + }); + } + + // Used to open both the edit and view more modals + handleOpenModal(actionItem) { + return modalType => { + const modalOpen = + modalType === 'edit' ? 'editModalOpen' : 'viewMoreModalOpen'; + this.setState({ + modalActionItem: actionItem, + [modalOpen]: true, + }); + }; + } + + editActionItem( + title, + description, + categorySelected, + dueDate, + addToTemplates, + participantId, + actionItemId, + actionItem, + ) { + this.setState(prevState => { + const newSelectedActionItems = prevState.selectedActionItems.map(item => { + const itemCopy = { ...item }; + if (this.checkActionItemsEqual(actionItem, item)) { + // id needs to be null so eheckmark doesn't appear + itemCopy.id = null; + itemCopy.title = title; + itemCopy.description = description; + itemCopy.category = categorySelected; + itemCopy.dueDate = dueDate; + } + return itemCopy; + }); + return { selectedActionItems: newSelectedActionItems }; + }); + } + handleChange(name) { return event => { const { value } = event.target; @@ -128,7 +187,13 @@ class ActionItemCreationPage extends React.Component { console.log(assignments[0]); apiPost('/api/assignments', formData) .then((res) => console.log(res)) + this.setState({ submissionStatus: 'loading' }); + apiPost('/api/assignments', body) + .then(() => + this.setState({ submissionStatus: 'complete', submitFailed: false }), + ) .catch(error => { + this.setState({ submissionStatus: 'error' }); Sentry.configureScope(function(scope) { scope.setExtra('file', 'ActionItemCreationPage'); scope.setExtra('action', 'apiPost (handleSubmit)'); @@ -165,7 +230,11 @@ class ActionItemCreationPage extends React.Component { removeSelectedActionItem(actionItem) { this.setState(prevState => { const filteredActionItems = prevState.selectedActionItems.filter( - item => !this.checkActionItemsEqual(actionItem, item), + item => + !( + this.checkActionItemsEqual(actionItem, item) && + actionItem.id === item.id + ), ); return { selectedActionItems: filteredActionItems }; }); @@ -242,7 +311,10 @@ class ActionItemCreationPage extends React.Component { selectActionItemTemplate(actionItem) { this.setState(prevState => ({ - selectedActionItems: [actionItem, ...prevState.selectedActionItems], + selectedActionItems: [ + { ...actionItem }, + ...prevState.selectedActionItems, + ], })); } @@ -306,14 +378,17 @@ class ActionItemCreationPage extends React.Component { let rightComponent; let leftComponentText; let rightComponentText; + let headerText; switch (stepSize) { case 0: leftComponentText = 'Assignments'; rightComponentText = 'Add Assignments'; + headerText = 'Add Assignments to List'; leftComponent = ( ); rightComponent = ( @@ -335,12 +410,15 @@ class ActionItemCreationPage extends React.Component { selectActionItemTemplate={this.selectActionItemTemplate} deleteTemplate={this.deleteTemplate} setFile={this.handleFile} + handleOpenModal={this.handleOpenModal} /> ); break; case 1: leftComponentText = 'Students'; rightComponentText = 'Add Students'; + headerText = 'Add Students to Assignments'; + leftComponent = ( ); break; @@ -378,12 +459,14 @@ class ActionItemCreationPage extends React.Component { rightComponent = null; leftComponentText = null; rightComponentText = null; + headerText = null; } return { leftComponent, rightComponent, leftComponentText, rightComponentText, + headerText, }; } @@ -521,14 +604,48 @@ class ActionItemCreationPage extends React.Component { leftComponentText, rightComponent, rightComponentText, + headerText, } = this.getMainComponents(this.state.step); const buttonsGrid = this.getButtonsGrid(this.state.step); - const submissionError = this.state.submitFailed && this.state.step === 2; return (
+ {this.state.viewMoreModalOpen ? ( + + ) : null} + {this.state.editModalOpen ? ( + + ) : null} + {this.state.submissionStatus ? ( + + ) : null} + { @@ -543,25 +660,6 @@ class ActionItemCreationPage extends React.Component { message="There must be at least 1 assignment and 1 student" /> - - - - Bulk assignment successfully submitted. Press the button to - refresh. - - - - - - - - + + + {`Step + - Add Assignments to List + {headerText} diff --git a/app/javascript/components/ActionItemCreationPage/styles.js b/app/javascript/components/ActionItemCreationPage/styles.js index 66e93201..fbc6281f 100644 --- a/app/javascript/components/ActionItemCreationPage/styles.js +++ b/app/javascript/components/ActionItemCreationPage/styles.js @@ -1,8 +1,11 @@ const styles = theme => ({ - '@global': { - body: { - margin: '0px', - }, + pageStyle: { + minHeight: '100vh', + width: '100%', + minWidth: '1000px', + margin: '0px', + backgroundColor: theme.palette.common.white, + overflow: 'none', }, snackbarStyle: { backgroundColor: 'red', @@ -11,6 +14,7 @@ const styles = theme => ({ backgroundColor: theme.palette.common.lightestGrey, padding: '2%', minWidth: '950px', + borderRadius: theme.shape.borderRadius, }, iconStyle: { backgroundColor: theme.palette.common.indigo, @@ -30,6 +34,9 @@ const styles = theme => ({ paddingLeft: '16px', paddingRight: '16px', }, + stepperStyle: { + paddingTop: '10px', + }, underlineStyle: { color: theme.palette.common.indigo, fontSize: '16px', diff --git a/app/javascript/components/ActionItemDisplayParticipants/styles.js b/app/javascript/components/ActionItemDisplayParticipants/styles.js index d05edc5f..28b22268 100644 --- a/app/javascript/components/ActionItemDisplayParticipants/styles.js +++ b/app/javascript/components/ActionItemDisplayParticipants/styles.js @@ -23,7 +23,7 @@ export const styles = theme => ({ borderRadius: '10px', border: 1, width: '400px', - minHeight: '470px', + height: '460px', paddingTop: '30px', paddingLeft: '20px', paddingRight: '20px', diff --git a/app/javascript/components/ActionItemForm/index.js b/app/javascript/components/ActionItemForm/index.js index 2b76f396..3d7aa504 100644 --- a/app/javascript/components/ActionItemForm/index.js +++ b/app/javascript/components/ActionItemForm/index.js @@ -84,19 +84,19 @@ function ActionItemForm({ - + - SEARCH BY CATEGORY + CHOOSE CATEGORY - + {categoryList.slice(0, 4)} - + {categoryList.slice(4)} @@ -176,6 +176,7 @@ function ActionItemForm({ onClick={() => { if (allFieldsFilled) { createActionItem(addToTemplates); + setAddToTemplates(false); setFailedSubmit(false); } else { setFailedSubmit(true); diff --git a/app/javascript/components/ActionItemList/index.js b/app/javascript/components/ActionItemList/index.js index 916f45a9..587865be 100644 --- a/app/javascript/components/ActionItemList/index.js +++ b/app/javascript/components/ActionItemList/index.js @@ -1,6 +1,7 @@ import React from 'react'; import Grid from '@material-ui/core/Grid'; import { withStyles } from '@material-ui/core/styles'; +import Paper from '@material-ui/core/Paper'; import ActionItemCard from 'components/ActionItemCard'; import PropTypes from 'prop-types'; import styles from './styles'; @@ -9,38 +10,41 @@ function ActionItemList({ classes, selectedActionItems, removeSelectedActionItem, + handleOpenModal, }) { - const selectedCards = selectedActionItems.map((actionItem, i) => ( - - removeSelectedActionItem(actionItem)} - /> - + const selectedCards = selectedActionItems.map(actionItem => ( + removeSelectedActionItem(actionItem)} + /> )); return ( - - {selectedCards} - + + + {selectedCards} + + ); } ActionItemList.propTypes = { classes: PropTypes.object.isRequired, selectedActionItems: PropTypes.array.isRequired, + handleOpenModal: PropTypes.func.isRequired, removeSelectedActionItem: PropTypes.func, }; diff --git a/app/javascript/components/ActionItemList/styles.js b/app/javascript/components/ActionItemList/styles.js index 643e66c9..35c583fe 100644 --- a/app/javascript/components/ActionItemList/styles.js +++ b/app/javascript/components/ActionItemList/styles.js @@ -2,10 +2,16 @@ const styles = theme => ({ listStyle: { width: '400px', overflowY: 'scroll', - backgroundColor: theme.palette.common.white, - height: '500px', marginBottom: '20px', }, + formStyle: { + padding: '10px', + height: '475px', + display: 'block', + overflowY: 'scroll', + backgroundColor: theme.palette.common.lightestGrey, + boxShadow: 'none', + }, }); export default styles; diff --git a/app/javascript/components/ActionItemModal/index.js b/app/javascript/components/ActionItemModal/index.js index a0466ac7..5f656624 100644 --- a/app/javascript/components/ActionItemModal/index.js +++ b/app/javascript/components/ActionItemModal/index.js @@ -35,7 +35,7 @@ class ActionItemForm extends React.Component { }; handleSubmit = () => { - const { participantId, actionItemId } = this.props; + const { participantId, actionItemId, actionItem } = this.props; const { title, description, @@ -53,6 +53,7 @@ class ActionItemForm extends React.Component { addToTemplates, participantId, actionItemId, + actionItem, ); this.props.handleClose(); } else { @@ -260,6 +261,7 @@ ActionItemForm.propTypes = { open: PropTypes.bool.isRequired, participantId: PropTypes.number, actionItemId: PropTypes.number, + actionItem: PropTypes.object, handleClose: PropTypes.func.isRequired, handleSubmit: PropTypes.func.isRequired, }; diff --git a/app/javascript/components/ActionItemSearchParticipants/styles.js b/app/javascript/components/ActionItemSearchParticipants/styles.js index 36c582be..a7cf1d1d 100644 --- a/app/javascript/components/ActionItemSearchParticipants/styles.js +++ b/app/javascript/components/ActionItemSearchParticipants/styles.js @@ -51,8 +51,7 @@ export const styles = () => ({ searchScroll: { overflowY: 'scroll', left: 0, - minHeight: '220px', - height: '30vh', + height: '210px', top: 0, }, diff --git a/app/javascript/components/AddFromExistingForm/index.js b/app/javascript/components/AddFromExistingForm/index.js index e1af2c8e..2c295793 100644 --- a/app/javascript/components/AddFromExistingForm/index.js +++ b/app/javascript/components/AddFromExistingForm/index.js @@ -119,7 +119,9 @@ class AddFromExistingForm extends React.Component { ? () => this.props.removeSelectedActionItem(template) : () => this.handleOpenDateModal(template) } - lastEntry={filteredTemplates.length - 1 === i} + handleOpenModal={this.props.handleOpenModal(template)} + // Border bottom styling should be added to all cards except the last + addBorderBottom={filteredTemplates.length - 1 !== i} removeActionItem={() => this.props.deleteTemplate(template)} /> @@ -225,7 +227,7 @@ class AddFromExistingForm extends React.Component { filteredTemplates ) : ( - No templates! + No assessments found )} @@ -242,6 +244,7 @@ AddFromExistingForm.propTypes = { selectedActionItemIds: PropTypes.instanceOf(Set).isRequired, selectActionItemTemplate: PropTypes.func.isRequired, removeSelectedActionItem: PropTypes.func.isRequired, + handleOpenModal: PropTypes.func.isRequired, deleteTemplate: PropTypes.func.isRequired, }; diff --git a/app/javascript/components/CaseNoteCard/index.js b/app/javascript/components/CaseNoteCard/index.js index 995c36c0..270089c3 100644 --- a/app/javascript/components/CaseNoteCard/index.js +++ b/app/javascript/components/CaseNoteCard/index.js @@ -8,11 +8,10 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core/styles'; import MoreHorizIcon from '@material-ui/icons/MoreHoriz'; -import { Menu, IconButton, Grid, Paper } from '@material-ui/core/'; +import { Menu, IconButton, Grid, Paper, Button } from '@material-ui/core/'; import MUIRichTextEditor from 'mui-rte'; import CaseNoteForm from 'components/CaseNoteForm'; import DeleteModal from 'components/DeleteModal'; -import CaseNoteCardModal from 'components/CaseNoteCardModal'; import styles from './styles'; function CaseNoteCard({ @@ -24,6 +23,7 @@ function CaseNoteCard({ participantId, showMenu, updateCaseNote, + handleOpenViewMore, }) { const [anchorEl, setAnchorEl] = useState(null); const handleMenuClick = event => { @@ -78,29 +78,33 @@ function CaseNoteCard({ ); return ( - - - - - -

{title}

-
- - {showMenu ? renderMenuItems() : null} - + + + + +

{title}

-
- -
+ + {showMenu ? renderMenuItems() : null} + +
+
+ +
- - - - - + + + + -
-
+
+
); } @@ -114,6 +118,7 @@ CaseNoteCard.propTypes = { participantId: PropTypes.number, showMenu: PropTypes.bool, updateCaseNote: PropTypes.func, + handleOpenViewMore: PropTypes.func.isRequired, }; export default withStyles(styles)(CaseNoteCard); diff --git a/app/javascript/components/CaseNoteCard/styles.js b/app/javascript/components/CaseNoteCard/styles.js index f71b0e69..e976fcdb 100644 --- a/app/javascript/components/CaseNoteCard/styles.js +++ b/app/javascript/components/CaseNoteCard/styles.js @@ -4,17 +4,17 @@ * This contains all the styles for the CaseNoteCard container. */ -export const styles = () => ({ +export const styles = theme => ({ buttonStyle: { marginTop: '5px', marginBottom: '10px', }, caseNoteCardStyle: { - marginLeft: '20px', padding: '20px', boxShadow: '0px 4px 10px rgba(0, 0, 0, 0.15)', - borderRadius: '10px', + borderRadius: theme.shape.borderRadius, height: '240px', + marginTop: '20px', }, caseNoteDescStyle: { height: '105px', diff --git a/app/javascript/components/CaseNoteCardModal/index.js b/app/javascript/components/CaseNoteCardModal/index.js deleted file mode 100644 index 6957dfb4..00000000 --- a/app/javascript/components/CaseNoteCardModal/index.js +++ /dev/null @@ -1,64 +0,0 @@ -import React, { useState } from 'react'; -import PropTypes from 'prop-types'; -import MUIRichTextEditor from 'mui-rte'; -import 'draft-js/dist/Draft.css'; -import 'draftail/dist/draftail.css'; -import { withStyles } from '@material-ui/core/styles'; -import { Button, Dialog, Grid, Paper } from '@material-ui/core/'; -import styles from './styles'; - - -function CaseNoteCardModal({ classes, description, title }) { - const [open, setOpen] = useState(false); - - return ( - <> -
- -
- - setOpen(false)} - aria-labelledby="form-dialog-title" - maxWidth="md" - > -
-
- - -

{title}

-
- - - -
- -
-
-
-
-
-
-
- - ); -} - -CaseNoteCardModal.propTypes = { - classes: PropTypes.object.isRequired, - description: PropTypes.string, - title: PropTypes.string, -}; - -export default withStyles(styles)(CaseNoteCardModal); diff --git a/app/javascript/components/CaseNoteContainer/index.js b/app/javascript/components/CaseNoteContainer/index.js index bfa707b4..9c9c94e3 100644 --- a/app/javascript/components/CaseNoteContainer/index.js +++ b/app/javascript/components/CaseNoteContainer/index.js @@ -6,6 +6,7 @@ import Container from '@material-ui/core/Container'; import Grid from '@material-ui/core/Grid'; import CaseNoteForm from 'components/CaseNoteForm'; import CaseNoteCard from 'components/CaseNoteCard'; +import ViewMoreModal from 'components/ViewMoreModal'; import PropTypes from 'prop-types'; import styles from './styles'; @@ -16,9 +17,22 @@ class CaseNoteContainer extends React.Component { caseNotes: this.props.caseNotes, participant: this.props.participant, userType: this.props.userType, + title: '', + description: '', + modalOpen: false, }; this.appendCaseNote = this.appendCaseNote.bind(this); this.updateCaseNote = this.updateCaseNote.bind(this); + this.handleCloseViewMoreModal = this.handleCloseViewMoreModal.bind(this); + this.handleOpenViewMoreModal = this.handleOpenViewMoreModal.bind(this); + } + + handleCloseViewMoreModal() { + this.setState({ modalOpen: false, title: '', description: '' }); + } + + handleOpenViewMoreModal(title, description) { + this.setState({ title, description, modalOpen: true }); } formatDate(dateString) { @@ -78,6 +92,7 @@ class CaseNoteContainer extends React.Component { participantId={this.state.participant.id} showMenu={this.state.userType === 'staff'} updateCaseNote={this.updateCaseNote} + handleOpenViewMore={this.handleOpenViewMoreModal} /> )); return caseNoteCards; @@ -107,6 +122,13 @@ class CaseNoteContainer extends React.Component { return ( <> + diff --git a/app/javascript/components/EnhancedTable/index.js b/app/javascript/components/EnhancedTable/index.js index cdad7b75..dc09d976 100644 --- a/app/javascript/components/EnhancedTable/index.js +++ b/app/javascript/components/EnhancedTable/index.js @@ -95,7 +95,7 @@ function EnhancedTable(props) { const [orderBy, setOrderBy] = React.useState('name'); const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(10); - const [selectedCat, setSelectedCat] = React.useState('name') + const [selectedCat, setSelectedCat] = React.useState('name'); const { rows } = props; const { headCells } = props; @@ -105,7 +105,7 @@ function EnhancedTable(props) { const isAsc = orderBy === property && order === 'asc'; setOrder(isAsc ? 'desc' : 'asc'); setOrderBy(property); - setSelectedCat(property) + setSelectedCat(property); }; const handleChangePage = (event, newPage) => { @@ -142,19 +142,18 @@ function EnhancedTable(props) { .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) .map(row => ( - { - type != "studio" ? - - : - - } + {type !== 'studio' ? ( + + ) : ( + + )} ))} {emptyRows > 0 && ( @@ -183,6 +182,7 @@ EnhancedTable.propTypes = { rows: PropTypes.array.isRequired, headCells: PropTypes.array.isRequired, classes: PropTypes.object.isRequired, + type: PropTypes.string, }; export default withStyles(styles)(EnhancedTable); diff --git a/app/javascript/components/LoadModal/index.js b/app/javascript/components/LoadModal/index.js new file mode 100644 index 00000000..2b9f34eb --- /dev/null +++ b/app/javascript/components/LoadModal/index.js @@ -0,0 +1,96 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import errorMailbox from 'images/error_mailbox'; +import loadMail from 'images/load_mail'; +import successMailbox from 'images/success_mailbox'; +import { + Dialog, + DialogActions, + DialogContent, + DialogContentText, + Fab, + Typography, + Grid, +} from '@material-ui/core'; +import styles from './styles'; + +function LoadModal({ classes, status, handleClick }) { + const getText = () => { + let titleText; + let buttonText; + let statusImage; + switch (status) { + case 'loading': + titleText = 'Assigning...'; + buttonText = null; + statusImage = loadMail; + break; + case 'complete': + titleText = 'Successfully Assigned!'; + buttonText = 'CREATE NEW'; + statusImage = successMailbox; + break; + case 'error': + titleText = 'Failed to Assign'; + buttonText = 'TRY AGAIN'; + statusImage = errorMailbox; + break; + default: + titleText = null; + buttonText = null; + statusImage = null; + } + return { titleText, buttonText, statusImage }; + }; + + const { titleText, buttonText, statusImage } = getText(); + + return ( + + + + + + {titleText} + + + + + + {titleText} + + + + + + {buttonText ? ( + + + {buttonText} + + + ) : null} + + + + + ); +} + +LoadModal.propTypes = { + classes: PropTypes.object.isRequired, + status: PropTypes.string.isRequired, + handleClick: PropTypes.func.isRequired, +}; +export default withStyles(styles)(LoadModal); diff --git a/app/javascript/components/LoadModal/styles.js b/app/javascript/components/LoadModal/styles.js new file mode 100644 index 00000000..ce3db33f --- /dev/null +++ b/app/javascript/components/LoadModal/styles.js @@ -0,0 +1,39 @@ +const styles = theme => ({ + modalStyle: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: '25%', + height: 'auto', + minWidth: '400px', + minHeight: '335px', + padding: '50px 0px', + }, + iconStyle: { + backgroundColor: theme.palette.common.indigo, + '&:hover': { + backgroundColor: theme.palette.common.indigo, + }, + marginTop: '27px', + boxShadow: 'None', + }, + categoryButtonStyle: { + textAlign: 'center', + fontWeight: 500, + fontSize: '14px', + lineHeight: '16px', + width: '135px', + color: theme.palette.common.white, + paddingLeft: '16px', + paddingRight: '16px', + }, + textStyle: { + fontFamily: 'Roboto', + fontStyle: 'normal', + fontWeight: '500', + fontSize: '18px', + lineHeight: '21px', + }, +}); + +export default styles; diff --git a/app/javascript/components/Main/index.js b/app/javascript/components/Main/index.js index 05b3147a..8fbc1067 100644 --- a/app/javascript/components/Main/index.js +++ b/app/javascript/components/Main/index.js @@ -62,6 +62,7 @@ function Main(props) { return ; case 'Assessments': return ; + default: } }; @@ -100,12 +101,15 @@ function Main(props) { return ; case 'StudioAssessmentDashboard': return ( - + ); case 'ActionItemCreationPage': return ( ); + default: } }; @@ -133,11 +137,13 @@ function Main(props) {
Sign Out
{props.isAdmin ? renderAdminButton() : null} - {Object.entries({ - Dashboard: '/', - 'Bulk Assign': '/assignments', - Assessments: '/studio_assessments', - }).map(n => getButton(n[0], n[1]))} + {props.userType !== 'participant' + ? Object.entries({ + Dashboard: '/', + 'Bulk Assign': '/assignments', + Assessments: '/studio_assessments', + }).map(n => getButton(n[0], n[1])) + : null}
diff --git a/app/javascript/components/PaperworkList/styles.js b/app/javascript/components/PaperworkList/styles.js index ee58aaca..6be47eca 100644 --- a/app/javascript/components/PaperworkList/styles.js +++ b/app/javascript/components/PaperworkList/styles.js @@ -7,7 +7,7 @@ const styles = theme => ({ containerStyle: { padding: '18px 28px', - borderRadius: 10, + borderRadius: theme.shape.borderRadius, marginLeft: 0, marginRight: 0, }, diff --git a/app/javascript/components/ParticipantCard/index.js b/app/javascript/components/ParticipantCard/index.js index 420b9e65..76c2a7fb 100644 --- a/app/javascript/components/ParticipantCard/index.js +++ b/app/javascript/components/ParticipantCard/index.js @@ -37,7 +37,7 @@ function ParticipantCard({ classes, participant }) { ); @@ -55,7 +55,7 @@ function ParticipantCard({ classes, participant }) { > {participant.name} - +
{participant.status.toUpperCase()}
@@ -76,6 +76,10 @@ function ParticipantCard({ classes, participant }) { incrementNumCaseNotes={() => setNumCaseNotes(numCaseNotes + 1)} > + + {participant.assignmentsCompleted} / {participant.assignmentsCount}{' '} + completed + {questionnaireStatus} ({ iconLarge: { - width: 35, - height: 35, - minWidth: 35, - minHeight: 35, + width: 30, + height: 30, + minWidth: 30, + minHeight: 30, }, name: { maxWidth: 80, @@ -15,13 +15,14 @@ const styles = theme => ({ backgroundColor: theme.palette.common.r1, }, status: { - width: 52, - height: 52, - borderRadius: '100%', + width: 80, + height: 25, + borderRadius: 14, textAlign: 'center', verticalAlign: 'middle', - lineHeight: '52px', + lineHeight: '25px', color: theme.palette.common.white, + fontSize: '12px', backgroundColor: ({ participant }) => { switch (participant.status.toUpperCase()) { case 'R0': diff --git a/app/javascript/components/ParticipantShowPage/index.js b/app/javascript/components/ParticipantShowPage/index.js index e70cc330..1f65082c 100644 --- a/app/javascript/components/ParticipantShowPage/index.js +++ b/app/javascript/components/ParticipantShowPage/index.js @@ -80,7 +80,7 @@ class ParticipantShowPage extends React.Component { item container direction="row" - justify="space-evenly" + justify="flex-start" spacing={1} > diff --git a/app/javascript/components/QuestionnaireForm/index.js b/app/javascript/components/QuestionnaireForm/index.js index cd6ad83c..3aafd471 100644 --- a/app/javascript/components/QuestionnaireForm/index.js +++ b/app/javascript/components/QuestionnaireForm/index.js @@ -9,7 +9,19 @@ import { DialogContent, DialogContentText, TextField, + Radio, + RadioGroup, + FormControlLabel, + Select, + MenuItem, + InputLabel, + FormControl, } from '@material-ui/core/'; +import DateFnsUtils from '@date-io/date-fns'; +import { + MuiPickersUtilsProvider, + KeyboardDatePicker, +} from '@material-ui/pickers'; import styles from './styles'; import ActiveStorageProvider from 'react-activestorage-provider' @@ -30,6 +42,7 @@ class QuestionnaireForm extends React.Component { questionnaire[k] = this.props.questionnaire[k]; } }); + questionnaire.validPhone = true; this.setState({ questionnaire, }); @@ -101,6 +114,64 @@ class QuestionnaireForm extends React.Component { })); } + handlePhoneChange(e) { + const { id } = e.target; + const { value } = e.target; + const regex = /^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/; + const isValid = regex.test(value); + if (isValid || value === '') { + this.setState(s => ({ + questionnaire: { + ...s.questionnaire, + validPhone: true, + }, + })); + } else { + this.setState(s => ({ + questionnaire: { + ...s.questionnaire, + validPhone: false, + }, + })); + } + + this.setState(s => ({ + questionnaire: { + ...s.questionnaire, + [id]: value, + }, + })); + } + + handleRadioChange(e, fieldName, newValue) { + this.setState(s => ({ + questionnaire: { + ...s.questionnaire, + [fieldName]: newValue, + }, + })); + } + + handleSelectChange(e, fieldName) { + const { value } = e.target; + console.log(value); + this.setState(s => ({ + questionnaire: { + ...s.questionnaire, + [fieldName]: value, + }, + })); + } + + handleDateChange(date, fieldName) { + this.setState(s => ({ + questionnaire: { + ...s.questionnaire, + [fieldName]: date, + }, + })); + } + createTextForm(fieldName, fieldValue, contentText) { // content text is prompt/title for the text box // field name is the name of the field that will be filled in the database @@ -117,11 +188,187 @@ class QuestionnaireForm extends React.Component { margin="dense" maxRows={20} /> - ); + ); } + if (fieldName === 'DOC_status') { + return ( +
+ + {contentText} + + + } + label="WR" + onChange={e => this.handleRadioChange(e, fieldName, 'WR')} + checked={this.state.questionnaire.DOC_status === 'WR'} + /> + } + label="GRE" + onChange={e => this.handleRadioChange(e, fieldName, 'GRE')} + checked={this.state.questionnaire.DOC_status === 'GRE'} + /> + } + label="Community Placement" + onChange={e => + this.handleRadioChange(e, fieldName, 'Community Placement') + } + checked={ + this.state.questionnaire.DOC_status === 'Community Placement' + } + /> + } + label="Released with placement" + onChange={e => + this.handleRadioChange(e, fieldName, 'Released with placement') + } + checked={ + this.state.questionnaire.DOC_status === + 'Released with placement' + } + /> + } + label="Released without placement" + onChange={e => + this.handleRadioChange( + e, + fieldName, + 'Released without placement', + ) + } + checked={ + this.state.questionnaire.DOC_status === + 'Released without placement' + } + /> + +
+ ); + } + if (fieldName === 'race_and_ethnicities') { + return ( +
+ + {contentText} + + + + Select Race/Ethnicity + + + +
+ ); + } + if (fieldName === 'course_completion') { + return ( +
+ + {contentText} + + + } + label="completed" + onChange={e => this.handleRadioChange(e, fieldName, 'completed')} + checked={ + this.state.questionnaire.course_completion === 'completed' + } + /> + } + label="incomplete" + onChange={e => this.handleRadioChange(e, fieldName, 'incomplete')} + checked={ + this.state.questionnaire.course_completion === 'incomplete' + } + /> + +
+ ); + } + if (fieldName === 'birthdate') { + return ( +
+ + {contentText} + + + this.handleDateChange(e, fieldName)} + format="MM/dd/yyyy" + /> + +
+ ); + } + if (fieldName === 'phone_number') { + return ( +
+ + {contentText} + + this.handlePhoneChange(e)} + error={!this.state.questionnaire.validPhone} + helperText={ + !this.state.questionnaire.validPhone + ? 'Please enter a valid phone number.' + : '' + } + variant="outlined" + id={fieldName} + multiline + type="text" + margin="dense" + defaultValue={fieldValue} + maxRows={20} + /> +
+ ); } return (
- {contentText} + + {contentText} + this.handleTextFormChange(e)} @@ -150,6 +397,13 @@ class QuestionnaireForm extends React.Component { .replace('-', ' ') .replace('_', ' '), ); + if (f === 'emergency_contact_2_name') { + sentenceCase = 'Second Emergency Contact (optional)'; + } else if (f === 'emergency_contact_2_phone_number') { + sentenceCase = 'Second Emergency Contact Phone Number (optional)'; + } else if (f === 'emergency_contact_2_relationship') { + sentenceCase = 'Second Emergency Contact Relationship (optional)'; + } return (
diff --git a/app/javascript/components/QuestionnaireForm/styles.js b/app/javascript/components/QuestionnaireForm/styles.js index 5fdf8795..25b3b082 100644 --- a/app/javascript/components/QuestionnaireForm/styles.js +++ b/app/javascript/components/QuestionnaireForm/styles.js @@ -21,6 +21,19 @@ const styles = () => ({ questionnaireEntry: { marginBottom: 20, }, + questionnaireLabel: { + marginBottom: '0px', + }, + radioGroup: { + marginTop: '5px', + }, + selectMenu: { + minWidth: 200, + marginTop: '8px', + }, + selectLabelText: { + marginLeft: '2px', + }, }); export default styles; diff --git a/app/javascript/components/QuestionnaireModal/index.js b/app/javascript/components/QuestionnaireModal/index.js index 0efce3ec..b0758911 100644 --- a/app/javascript/components/QuestionnaireModal/index.js +++ b/app/javascript/components/QuestionnaireModal/index.js @@ -1,9 +1,3 @@ -/** - * - * QuestionnaireModal - * - */ - import React, { memo, useState } from 'react'; import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core/styles'; @@ -21,7 +15,8 @@ function QuestionnaireModal({ userType, }) { const [open, setOpen] = useState(false); - const qType = questionnaireType.toUpperCase(); + const qType = + questionnaireType.charAt(0).toUpperCase() + questionnaireType.slice(1); let content; if (userType === 'staff') { @@ -57,7 +52,9 @@ function QuestionnaireModal({ classes={{ paper: classes.dialog }} > - {qType} INFORMATION    + + {qType} Information + {content} diff --git a/app/javascript/components/QuestionnaireModal/styles.js b/app/javascript/components/QuestionnaireModal/styles.js index 4f72479b..bd309d38 100644 --- a/app/javascript/components/QuestionnaireModal/styles.js +++ b/app/javascript/components/QuestionnaireModal/styles.js @@ -6,12 +6,16 @@ const styles = theme => ({ dialog: { - borderRadius: 20, + borderRadius: theme.shape.borderRadius, }, title: { backgroundColor: theme.palette.primary.main, color: theme.palette.primary.contrastText, - padding: '56px 114px 56px 56px', + padding: '20px 145px 20px 25px', + marginBottom: '30px', + }, + titleText: { + fontSize: '24px', }, }); diff --git a/app/javascript/components/StaffDashboard/index.js b/app/javascript/components/StaffDashboard/index.js index 58486250..97911ce1 100644 --- a/app/javascript/components/StaffDashboard/index.js +++ b/app/javascript/components/StaffDashboard/index.js @@ -71,6 +71,12 @@ class StaffDashboard extends React.Component { label: 'Casenotes', sortable: true, }, + { + id: 'assignmentsCompleted', + disablePadding: false, + label: 'Assignments', + sortable: true, + }, { id: 'form_status', disablePadding: false, diff --git a/app/javascript/components/StudioAssessmentCard/index.js b/app/javascript/components/StudioAssessmentCard/index.js index c6fc461e..5a6aeeda 100644 --- a/app/javascript/components/StudioAssessmentCard/index.js +++ b/app/javascript/components/StudioAssessmentCard/index.js @@ -1,9 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core/styles'; -import styles from './styles'; import TableCell from '@material-ui/core/TableCell'; - +import styles from './styles'; class StudioAssessmentCard extends React.Component { constructor(props) { @@ -59,13 +58,19 @@ class StudioAssessmentCard extends React.Component { > {vc} - + {react} - + {db} - + {node} ({ containerStyle: { padding: '18px 28px', - borderRadius: 10, + borderRadius: theme.shape.borderRadius, marginLeft: 0, marginRight: 0, }, diff --git a/app/javascript/components/StudioAssessmentModal/styles.js b/app/javascript/components/StudioAssessmentModal/styles.js index b6a7c042..a4287a58 100644 --- a/app/javascript/components/StudioAssessmentModal/styles.js +++ b/app/javascript/components/StudioAssessmentModal/styles.js @@ -6,7 +6,7 @@ const styles = theme => ({ dialog: { - borderRadius: theme.shape.borderRadius + borderRadius: theme.shape.borderRadius, }, title: { backgroundColor: theme.palette.primary.main, diff --git a/app/javascript/components/StudioAssessmentQuestion/questions.js b/app/javascript/components/StudioAssessmentQuestion/questions.js index 01f2870b..7f50a991 100644 --- a/app/javascript/components/StudioAssessmentQuestion/questions.js +++ b/app/javascript/components/StudioAssessmentQuestion/questions.js @@ -1,98 +1,95 @@ export const questions = [ - 'Understands the Big Picture of the Full Stack', - 'JavaScript Fundamentals', - 'Understands Version Control', - 'React Core Competencies', - 'NodeJs Core Competencies', - 'Database Core Competencies', - 'Problem Solving: Whiteboarding', - ]; - + 'Understands the Big Picture of the Full Stack', + 'JavaScript Fundamentals', + 'Understands Version Control', + 'React Core Competencies', + 'NodeJs Core Competencies', + 'Database Core Competencies', + 'Problem Solving: Whiteboarding', +]; + export const questionContent = [ - [ - 'Describe the roles of Html,Javascript, and CSS in a webpage.', - 'What distinguishes a web application from a static webpage?', - 'In a full stack web application, what is the client-side code typically responsible for? The server side code?', - 'Name a few ways in which data can be sent to a server from a web browser.', - 'What frameworks might be used on the client to help manage modifying the DOM?', - 'What technologies might be used on the server to deliver web pages to the browser?' - ], - [ - 'Explain the difference between var, let, and const?', - 'What is a closure?', - 'What is a prototype?', - 'How are apply, call, and bind methods on the function prototype used? Why would you use them?', - 'In a class method, what does "this" keyword refer to? In a top-level function?', - 'What is an anonymous function? An arrow function? What is "this" in each?' - ], - [ - 'What is Git?', - 'What are some advantages of using Git?' - ], - [ - 'What is a component?', - 'Name two ways you might define a component?', - 'Compare component properties versus state? How is each modified?', - 'What do we mean by the lifecycle" of a component? Talk about some lifecycle methods and what they are used for.' - ], - [ - 'What is a module?', - 'How does a module expose its public interface?', - 'Are there different kinds of interfaces a module can expose?', - 'When/how is asynchronous code executed? (getting at the event loop)' - ], - [ - 'Describe the difference between a relational DB and a json store such as Mongo.', - 'Describe the use of keys in both.', - 'How are relations between tables/collections established in either?', - 'Write a SQL query to return the top 5 results from a “People” table, sorted alphabetically by name, selecting “Name”, “Dob”, and “Email” fields.' - ], - [ - 'Write a function in pseudocode that will format a string.', - 'It will take in two parameters, a format string, and an array of string replacements.' - ], - ]; - + [ + 'Describe the roles of Html,Javascript, and CSS in a webpage.', + 'What distinguishes a web application from a static webpage?', + 'In a full stack web application, what is the client-side code typically responsible for? The server side code?', + 'Name a few ways in which data can be sent to a server from a web browser.', + 'What frameworks might be used on the client to help manage modifying the DOM?', + 'What technologies might be used on the server to deliver web pages to the browser?', + ], + [ + 'Explain the difference between var, let, and const?', + 'What is a closure?', + 'What is a prototype?', + 'How are apply, call, and bind methods on the function prototype used? Why would you use them?', + 'In a class method, what does "this" keyword refer to? In a top-level function?', + 'What is an anonymous function? An arrow function? What is "this" in each?', + ], + ['What is Git?', 'What are some advantages of using Git?'], + [ + 'What is a component?', + 'Name two ways you might define a component?', + 'Compare component properties versus state? How is each modified?', + 'What do we mean by the lifecycle" of a component? Talk about some lifecycle methods and what they are used for.', + ], + [ + 'What is a module?', + 'How does a module expose its public interface?', + 'Are there different kinds of interfaces a module can expose?', + 'When/how is asynchronous code executed? (getting at the event loop)', + ], + [ + 'Describe the difference between a relational DB and a json store such as Mongo.', + 'Describe the use of keys in both.', + 'How are relations between tables/collections established in either?', + 'Write a SQL query to return the top 5 results from a “People” table, sorted alphabetically by name, selecting “Name”, “Dob”, and “Email” fields.', + ], + [ + 'Write a function in pseudocode that will format a string.', + 'It will take in two parameters, a format string, and an array of string replacements.', + ], +]; + export const rubricItems = [ - [ - 'While they may recognize technologies, the student cannot articulate roles of varying technologies, let alone be able to decide what technology to use for a particular need or how it fits into the bigger picture.', - 'The student articulates that there are different technologies with varied roles, can name the technologies involved with different roles, but struggles to decide what technology or role is involved in a particular domain. Also struggles with understanding how the technologies fit together.', - 'The student articulates the varied technologies in a web stack, their roles, the roles of the client and server, how these technologies/roles fit together and can (mostly) decided where to implement varied needs such as authorization, validation, persistence, etc.', - ], - - [ - 'Can clearly articulate hoisting, scope, closures. Knows the role of “this” and can describe the value under varied circumstances. Knows OOP and FP features. May be squishy on the “...” operator, but recognizes it and has an idea of its use.', - 'Understands scope and this binding. May not know the hoisting difference between var and let, but knows what hoisting is. May not know closure or be able to articulate the concept (function plus context), but understands captured variables. Understands object encapsulation via classes/prototypes, but may not understand inheritance or clearly articulate the concepts.', - 'Does not understand core javascript concepts. May be able to say what is output in the sample code, but does not have an understanding of why. Does not know about classes/prototypes.', - ], - - [ - 'Understands that git is a version control system (should use this exact term) in order to manage the history of versions of a code/package/repository', - 'Understands the role of Git but is fuzzy on the nature/purpose of continuous deployment', - 'Does not understand the role of Git nor CD.', - ], - - [ - 'Has a solid grasp of components, how to manage state, component lifecycle, event callbacks, and lifting state. May not fully understand state management, but does understand that it’s immutable though may not know the word.', - 'Understands what components are and has an idea of their lifecycle. Has limited understanding of managing state, data binding, callbacks, and state lifting.', - 'Fails to understand any of: what a component is, that there are lifecycle methods, what the difference between props and state is, or how to hook up an event callback', - ], - - [ - 'Is able to describe various methods of declaring async code and can describe when they run. Understands what EventEmitters and streams are and how to use them. Begins', - 'Has an understanding of modules, async code, and node-core. May miss that these are patterns established by Node’s runtime environment, may not be able to enumerate async methods or fully grasp when it runs.', - 'Does not understand patterns. May know that async is code executed concurrently at a (possibly) later time, but does not know how and cannot write asynchronous code or identify when code is asynchronous.', - ], + [ + 'While they may recognize technologies, the student cannot articulate roles of varying technologies, let alone be able to decide what technology to use for a particular need or how it fits into the bigger picture.', + 'The student articulates that there are different technologies with varied roles, can name the technologies involved with different roles, but struggles to decide what technology or role is involved in a particular domain. Also struggles with understanding how the technologies fit together.', + 'The student articulates the varied technologies in a web stack, their roles, the roles of the client and server, how these technologies/roles fit together and can (mostly) decided where to implement varied needs such as authorization, validation, persistence, etc.', + ], + + [ + 'Can clearly articulate hoisting, scope, closures. Knows the role of “this” and can describe the value under varied circumstances. Knows OOP and FP features. May be squishy on the “...” operator, but recognizes it and has an idea of its use.', + 'Understands scope and this binding. May not know the hoisting difference between var and let, but knows what hoisting is. May not know closure or be able to articulate the concept (function plus context), but understands captured variables. Understands object encapsulation via classes/prototypes, but may not understand inheritance or clearly articulate the concepts.', + 'Does not understand core javascript concepts. May be able to say what is output in the sample code, but does not have an understanding of why. Does not know about classes/prototypes.', + ], + + [ + 'Understands that git is a version control system (should use this exact term) in order to manage the history of versions of a code/package/repository', + 'Understands the role of Git but is fuzzy on the nature/purpose of continuous deployment', + 'Does not understand the role of Git nor CD.', + ], + + [ + 'Has a solid grasp of components, how to manage state, component lifecycle, event callbacks, and lifting state. May not fully understand state management, but does understand that it’s immutable though may not know the word.', + 'Understands what components are and has an idea of their lifecycle. Has limited understanding of managing state, data binding, callbacks, and state lifting.', + 'Fails to understand any of: what a component is, that there are lifecycle methods, what the difference between props and state is, or how to hook up an event callback', + ], + + [ + 'Is able to describe various methods of declaring async code and can describe when they run. Understands what EventEmitters and streams are and how to use them. Begins', + 'Has an understanding of modules, async code, and node-core. May miss that these are patterns established by Node’s runtime environment, may not be able to enumerate async methods or fully grasp when it runs.', + 'Does not understand patterns. May know that async is code executed concurrently at a (possibly) later time, but does not know how and cannot write asynchronous code or identify when code is asynchronous.', + ], - [ - 'Knows the difference between organization of data in document stores and relational DBs. Can successfully write a basic SQL query. Has a notion of ACID principles and how that relates to transactions.', - 'Understands organization of data and relations between data entities in databases.', - 'Does not understand how data is organized in a database.', - ], + [ + 'Knows the difference between organization of data in document stores and relational DBs. Can successfully write a basic SQL query. Has a notion of ACID principles and how that relates to transactions.', + 'Understands organization of data and relations between data entities in databases.', + 'Does not understand how data is organized in a database.', + ], - [ - 'Gives a correct solution with no bugs (eventually). If their solution started with bugs, can figure out that those bugs exist.May have bugs initially but ought to be able to test their functions by walking through line by line with mock data and find the bugs.', - 'Gives a plausible solution but may have remaining bugs even after some hinting.', - 'Can’t arrive at a solution that even remotely prints out what’s required, even with subtle proctor hints and intervention.', - ], - ]; \ No newline at end of file + [ + 'Gives a correct solution with no bugs (eventually). If their solution started with bugs, can figure out that those bugs exist.May have bugs initially but ought to be able to test their functions by walking through line by line with mock data and find the bugs.', + 'Gives a plausible solution but may have remaining bugs even after some hinting.', + 'Can’t arrive at a solution that even remotely prints out what’s required, even with subtle proctor hints and intervention.', + ], +]; diff --git a/app/javascript/components/ViewMoreModal/index.js b/app/javascript/components/ViewMoreModal/index.js new file mode 100644 index 00000000..8579f872 --- /dev/null +++ b/app/javascript/components/ViewMoreModal/index.js @@ -0,0 +1,116 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import MUIRichTextEditor from 'mui-rte'; +import 'draft-js/dist/Draft.css'; +import 'draftail/dist/draftail.css'; +import { withStyles } from '@material-ui/core/styles'; +import { + Dialog, + Grid, + Paper, + Input, + Fab, + Typography, +} from '@material-ui/core/'; +import styles from './styles'; + +function ViewMoreModal({ + classes, + description, + title, + category, + dueDate, + isCaseNote, + open, + handleClose, +}) { + const renderRichText = desc => ( + + ); + const renderReadOnlyTextField = desc => ( + + ); + const renderCategory = categorySelected => ( + + + + {categorySelected.toUpperCase()} + + + + ); + const renderDueDate = date => { + if (dueDate) { + return ( + +

Due Date: {date}

+
+ ); + } + return null; + }; + + return ( + <> + +
+
+ + + +

{title}

+
+ {isCaseNote ? null : renderCategory(category)} +
+ {isCaseNote ? null : renderDueDate(dueDate)} + + +
+ {isCaseNote + ? renderRichText(description) + : renderReadOnlyTextField(description)} +
+
+
+
+
+
+
+ + ); +} + +ViewMoreModal.propTypes = { + classes: PropTypes.object.isRequired, + description: PropTypes.string, + title: PropTypes.string, + category: PropTypes.string, + dueDate: PropTypes.string, + open: PropTypes.bool.isRequired, + isCaseNote: PropTypes.bool, + handleClose: PropTypes.func.isRequired, +}; + +export default withStyles(styles)(ViewMoreModal); diff --git a/app/javascript/components/CaseNoteCardModal/styles.js b/app/javascript/components/ViewMoreModal/styles.js similarity index 65% rename from app/javascript/components/CaseNoteCardModal/styles.js rename to app/javascript/components/ViewMoreModal/styles.js index 4f01db15..018e559b 100644 --- a/app/javascript/components/CaseNoteCardModal/styles.js +++ b/app/javascript/components/ViewMoreModal/styles.js @@ -4,8 +4,7 @@ const styles = theme => ({ marginRight: '0', }, caseNoteDescStyle: { - marginLeft: '20px', - paddingTop: '20px', + margin: '20px', }, dialogStyle: { padding: '20px', @@ -37,6 +36,24 @@ const styles = theme => ({ marginBottom: '0', marginTop: '0', }, + dateTextStyle: { + color: theme.palette.common.white, + fontSize: '24px', + marginBottom: '0', + marginTop: '0', + }, + iconStyle: { + boxShadow: 'None', + backgroundColor: theme.palette.common.lighterBlue, + }, + categoryButtonStyle: { + fontSize: '10px', + textAlign: 'center', + width: 60, + paddingLeft: '8px', + paddingRight: '8px', + color: theme.palette.primary.main, + }, }); export default styles; diff --git a/app/javascript/components/styles.js b/app/javascript/components/styles.js index 3fd17c8d..accca6ac 100644 --- a/app/javascript/components/styles.js +++ b/app/javascript/components/styles.js @@ -55,7 +55,6 @@ export const styles = () => ({ height: '30px', display: 'flex', alignItems: 'center', - // alignContent: 'space-between', justifyContent: 'space-between', width: '100%', }, diff --git a/app/javascript/utils/theme.js b/app/javascript/utils/theme.js index 0fb7e2d9..4c6f58ae 100644 --- a/app/javascript/utils/theme.js +++ b/app/javascript/utils/theme.js @@ -7,7 +7,6 @@ export const theme = createMuiTheme({ lighterBlue: '#DCF0F2', indigo: '#5870EB', lightBlue: 'rgba(210, 220, 225, 0.63)', - lighterBlue: '#DCF0F2', purpleSecondary: '#DEE2FB', darkBlue: '#28303B', darkestBlue: '#29313C', diff --git a/app/policies/studio_assessment_policy.rb b/app/policies/studio_assessment_policy.rb index 7df46057..9cd09708 100644 --- a/app/policies/studio_assessment_policy.rb +++ b/app/policies/studio_assessment_policy.rb @@ -1,4 +1,8 @@ class StudioAssessmentPolicy < ApplicationPolicy + def index? + staff? + end + def create? staff? end @@ -24,7 +28,7 @@ def resolve if user.staff? scope.all else - scope.where([participant_id: user.participant.id]) + scope.where(participant_id: user.participant.id) end end end diff --git a/app/serializers/personal_questionnaire_serializer.rb b/app/serializers/personal_questionnaire_serializer.rb index 33901a17..c4448b45 100644 --- a/app/serializers/personal_questionnaire_serializer.rb +++ b/app/serializers/personal_questionnaire_serializer.rb @@ -1,18 +1,5 @@ class PersonalQuestionnaireSerializer < ActiveModel::Serializer attributes :id, - :doc_status, - :housing, - :mental_health, - :medical, - :transportation, - :clothing, - :significant_relationships, - :support_systems, - :doc_regulations, - :treatment, - :triggers_and_prevention, - :personal_needs, - :personal_goals, :birthdate, :phone_number, :pronouns, @@ -24,10 +11,23 @@ class PersonalQuestionnaireSerializer < ActiveModel::Serializer :emergency_contact_2_name, :emergency_contact_2_phone_number, :emergency_contact_2_relationship, + :significant_relationships, + :support_systems, + :mental_health, + :DOC_status, + :DOC_regulations, + :housing, + :medical, + :treatment, + :triggers_and_prevention, + :personal_needs, + :transportation, + :clothing, :financial_obligations, :resources_allocated, :orca_card, :state_assistance, + :personal_goals, :participant belongs_to :participant, serializer: SimpleParticipantSerializer diff --git a/app/serializers/professional_questionnaires_serializer.rb b/app/serializers/professional_questionnaires_serializer.rb index 628fbe1b..baf53717 100644 --- a/app/serializers/professional_questionnaires_serializer.rb +++ b/app/serializers/professional_questionnaires_serializer.rb @@ -1,8 +1,8 @@ class ProfessionalQuestionnairesSerializer < ActiveModel::Serializer - attributes :id, :course_completion, - :work_history, :job_search_materials, :professional_goals, - :barriers,:success_strategies, :education_history, :begin_skills_assessment_date, :end_skills_assessment_date, - :assigned_mentor, :participant + attributes :id, :course_completion, :education_history, + :work_history, :job_search_materials, :professional_goals, + :begin_skills_assessment_date, :end_skills_assessment_date, + :barriers, :assigned_mentor, :success_strategies, :participant belongs_to :participant, serializer: SimpleParticipantSerializer end diff --git a/db/migrate/20200502232032_capitalize_questionnaire_doc_columns.rb b/db/migrate/20200502232032_capitalize_questionnaire_doc_columns.rb new file mode 100644 index 00000000..64fc3cfa --- /dev/null +++ b/db/migrate/20200502232032_capitalize_questionnaire_doc_columns.rb @@ -0,0 +1,6 @@ +class CapitalizeQuestionnaireDocColumns < ActiveRecord::Migration[6.0] + def change + rename_column :personal_questionnaires, :doc_status, :DOC_status if column_exists?(:personal_questionnaires, :doc_status) && !column_exists?(:personal_questionnaires, :DOC_status) + rename_column :personal_questionnaires, :doc_regulations, :DOC_regulations if column_exists?(:personal_questionnaires, :doc_regulations) && !column_exists?(:personal_questionnaires, :DOC_regulations) + end +end diff --git a/db/schema.rb b/db/schema.rb index e479be01..f773bdb5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_04_24_023300) do +ActiveRecord::Schema.define(version: 2020_05_02_232032) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -92,7 +92,7 @@ end create_table "personal_questionnaires", force: :cascade do |t| - t.string "doc_status" + t.string "DOC_status" t.string "housing" t.string "mental_health" t.string "medical" @@ -100,7 +100,7 @@ t.string "clothing" t.string "significant_relationships" t.string "support_systems" - t.string "doc_regulations" + t.string "DOC_regulations" t.string "treatment" t.string "triggers_and_prevention" t.string "personal_needs" diff --git a/package.json b/package.json index 007674cf..2be1eaa4 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,15 @@ "@babel/plugin-transform-react-inline-elements": "^7.2.0", "@babel/preset-react": "^7.6.3", "@babel/types": "^7.7.2", + "@date-io/core": "^1.3.13", + "@date-io/date-fns": "1.x", + "@date-io/moment": "1.x", "@fortawesome/fontawesome-svg-core": "^1.2.25", "@fortawesome/free-solid-svg-icons": "^5.11.2", "@fortawesome/react-fontawesome": "^0.1.7", "@material-ui/core": "^4.9.10", "@material-ui/icons": "^4.5.1", + "@material-ui/pickers": "^3.2.10", "@material-ui/styles": "^4.9.10", "@rails/actioncable": "^6.0.0-alpha", "@rails/activestorage": "^6.0.0-alpha", @@ -43,6 +47,7 @@ "babel-eslint": "^10.0.3", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "dotenv": "^8.2.0", + "date-fns": "^2.12.0", "draft-js": "^0.11.2", "draft-js-plugins-editor": "^3.0.0", "draftail": "^1.3.0", @@ -61,8 +66,10 @@ "history": "^4.10.1", "jest-cli": "^24.9.0", "jest-dom": "^4.0.0", + "libphonenumber-js": "^1.7.51", "lint-staged": "^9.4.2", "material-ui-dropzone": "^3.0.0", + "moment": "^2.25.1", "mui-rte": "^1.8.0", "node-plop": "^0.23.0", "plop": "^2.5.3", @@ -74,13 +81,14 @@ "react-dom": "^16.12.0", "react-helmet": "^5.2.1", "react-intl": "^3.4.0", + "react-phone-number-input": "^3.0.22", "react-testing-library": "^8.0.1", "react_ujs": "^2.6.0", "stylelint": "^11.1.1", "stylelint-config-recommended": "^3.0.0", "trie-search": "^1.2.11", "turbolinks": "^5.2.0", - "validator": "^12.0.0", + "validator": "^13.0.0", "webpack": "^4.41.2" }, "version": "0.1.0", diff --git a/yarn.lock b/yarn.lock index 7769195b..901170c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -814,6 +814,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" +<<<<<<< HEAD "@babel/preset-react@^7.6.3": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.4.tgz#c6c97693ac65b6b9c0b4f25b948a8f665463014d" @@ -832,6 +833,20 @@ integrity sha512-6toWAfaALQjt3KMZQc6fABqZwUDDuWzz+cAfPhqyEnzxvdWOAkjwPNxgF8xlmo7OWLsSjaKjsskpKHRLaMArOA== dependencies: core-js-pure "^3.0.0" +======= +"@babel/runtime@^7.6.0": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" + integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.8.3": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" + integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== + dependencies: +>>>>>>> master regenerator-runtime "^0.13.4" "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": @@ -887,6 +902,25 @@ resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== +"@date-io/core@1.x", "@date-io/core@^1.3.13": + version "1.3.13" + resolved "https://registry.yarnpkg.com/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa" + integrity sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA== + +"@date-io/date-fns@1.x": + version "1.3.13" + resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-1.3.13.tgz#7798844041640ab393f7e21a7769a65d672f4735" + integrity sha512-yXxGzcRUPcogiMj58wVgFjc9qUYrCnnU9eLcyNbsQCmae4jPuZCDoIBR21j8ZURsM7GRtU62VOw5yNd4dDHunA== + dependencies: + "@date-io/core" "^1.3.13" + +"@date-io/moment@1.x": + version "1.3.13" + resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-1.3.13.tgz#56c2772bc4f6675fc6970257e6033e7a7c2960f0" + integrity sha512-3kJYusJtQuOIxq6byZlzAHoW/18iExJer9qfRF5DyyzdAk074seTuJfdofjz4RFfTd/Idk8WylOQpWtERqvFuQ== + dependencies: + "@date-io/core" "^1.3.13" + "@emotion/hash@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" @@ -1125,6 +1159,7 @@ dependencies: "@babel/runtime" "^7.4.4" +<<<<<<< HEAD "@material-ui/react-transition-group@^4.3.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@material-ui/react-transition-group/-/react-transition-group-4.3.0.tgz#92529142addb5cc179dbf42d246c7e3fe4d6104b" @@ -1139,6 +1174,24 @@ version "4.9.13" resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.9.13.tgz#08b3976bdd21c38bc076693d95834f97539f3b15" integrity sha512-lWlXJanBdHQ18jW/yphedRokHcvZD1GdGzUF/wQxKDsHwDDfO45ZkAxuSBI202dG+r1Ph483Z3pFykO2obeSRA== +======= +"@material-ui/pickers@^3.2.10": + version "3.2.10" + resolved "https://registry.yarnpkg.com/@material-ui/pickers/-/pickers-3.2.10.tgz#19df024895876eb0ec7cd239bbaea595f703f0ae" + integrity sha512-B8G6Obn5S3RCl7hwahkQj9sKUapwXWFjiaz/Bsw1fhYFdNMnDUolRiWQSoKPb1/oKe37Dtfszoywi1Ynbo3y8w== + dependencies: + "@babel/runtime" "^7.6.0" + "@date-io/core" "1.x" + "@types/styled-jsx" "^2.2.8" + clsx "^1.0.2" + react-transition-group "^4.0.0" + rifm "^0.7.0" + +"@material-ui/styles@^4.9.10": + version "4.9.10" + resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.9.10.tgz#182ccdd0bc8525a459486499bbaebcd92b0db3ab" + integrity sha512-EXIXlqVyFDnjXF6tj72y6ZxiSy+mHtrsCo3Srkm3XUeu3Z01aftDBy7ZSr3TQ02gXHTvDSBvegp3Le6p/tl7eA== +>>>>>>> master dependencies: "@babel/runtime" "^7.4.4" "@emotion/hash" "^0.8.0" @@ -1171,7 +1224,7 @@ resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.0.1.tgz#c4954063cdc196eb327ee62c041368b1aebb6d61" integrity sha512-wURPSY7/3+MAtng3i26g+WKwwNE3HEeqa/trDBR5+zWKmcjO+u9t7Npu/J1r+3dmIa/OeziN9D/18IrBKvKffw== -"@material-ui/utils@^4.9.12", "@material-ui/utils@^4.9.6": +"@material-ui/utils@^4.9.6": version "4.9.12" resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.9.12.tgz#0d639f1c1ed83fffb2ae10c21d15a938795d9e65" integrity sha512-/0rgZPEOcZq5CFA4+4n6Q6zk7fi8skHhH2Bcra8R3epoJEYy5PL55LuMazPtPH1oKeRausDV/Omz4BbgFsn1HQ== @@ -1504,6 +1557,13 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/styled-jsx@^2.2.8": + version "2.2.8" + resolved "https://registry.yarnpkg.com/@types/styled-jsx/-/styled-jsx-2.2.8.tgz#b50d13d8a3c34036282d65194554cf186bab7234" + integrity sha512-Yjye9VwMdYeXfS71ihueWRSxrruuXTwKCbzue4+5b2rjnQ//AtyM7myZ1BEhNhBQ/nL/RE7bdToUoLln2miKvg== + dependencies: + "@types/react" "*" + "@types/through@*": version "0.0.30" resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895" @@ -2784,7 +2844,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.6: +classnames@^2.2.5, classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -2870,6 +2930,11 @@ clsx@^1.0.2, clsx@^1.0.4: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA== +clsx@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" + integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3143,6 +3208,10 @@ cosmiconfig@^6.0.0: parse-json "^5.0.0" path-type "^4.0.0" yaml "^1.7.2" +country-flag-icons@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/country-flag-icons/-/country-flag-icons-1.2.1.tgz#166878b8734ada5c4c0a8ce9d9d05c9ddf272af5" + integrity sha512-iusfhFhJvYQzQjlVIJv4JoKKnGB+f4+vpi3zEU945ln/E+okPLzfz7jRBtInYIknOy2YTzcV2GAP45axi1R3/g== create-ecdh@^4.0.0: version "4.0.3" @@ -3472,6 +3541,11 @@ date-fns@^1.27.2: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== +date-fns@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.12.0.tgz#01754c8a2f3368fc1119cf4625c3dad8c1845ee6" + integrity sha512-qJgn99xxKnFgB1qL4jpxU7Q2t0LOn1p8KMIveef3UZD7kqjT3tpFNNdXJelEHhE+rUgffriXriw/sOSU+cS1Hw== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -5636,6 +5710,13 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== +input-format@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/input-format/-/input-format-0.3.0.tgz#f662b1667b6d067769f44c717bcfcc92554bee75" + integrity sha512-7ipaXJ5Hnd2o62IxLRTCMcl7AOPzxU2PTfDunPDIaaAjq+Q8DcjI4/nmPo3fXJUvdTCX97BlW8d+7ArUhVTxAA== + dependencies: + prop-types "^15.7.2" + inquirer@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" @@ -6851,6 +6932,14 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +libphonenumber-js@^1.7.45, libphonenumber-js@^1.7.51: + version "1.7.51" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.7.51.tgz#e84901179a154c8074f9c01214dd80b859598d74" + integrity sha512-YrmFi5rLnSMKp2tM0FkjIHGAlHyUo8pRP8u4DeMseX+gXDY96q7sgfy/Ty54nv0BqObYKzPJBUq4LMMNESjfBA== + dependencies: + minimist "^1.2.5" + xml2js "^0.4.17" + liftoff@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" @@ -7478,6 +7567,14 @@ minipass-pipeline@^1.2.2: integrity sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA== dependencies: minipass "^3.0.0" +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: version "2.9.0" @@ -7532,6 +7629,11 @@ mixin-deep@^1.2.0: dependencies: minimist "^1.2.5" +moment@^2.25.1: + version "2.25.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.25.1.tgz#1cb546dca1eccdd607c9324747842200b683465d" + integrity sha512-nRKMf9wDS4Fkyd0C9LXh2FFXinD+iwbJ5p/lh3CHitW9kZbRbJ8hCruiadiIXZVbeAqKZzqcTvHnK3mRhFjb6w== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -9661,6 +9763,22 @@ react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^16.8.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-phone-number-input@^3.0.22: + version "3.0.22" + resolved "https://registry.yarnpkg.com/react-phone-number-input/-/react-phone-number-input-3.0.22.tgz#4e694492388dc7350e687e2c7900a7c843f7d06d" + integrity sha512-LLQENqN3Pz4I/L/A5a4jrLezfIM++J/YLmejCqgs3K1aO0BKoTJIHlhRms1D0tApZUdXB8nDTQNLO5VGZcVDww== + dependencies: + classnames "^2.2.5" + country-flag-icons "^1.0.2" + input-format "^0.3.0" + libphonenumber-js "^1.7.45" + prop-types "^15.7.2" + react-side-effect@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.2.0.tgz#0e940c78faba0c73b9b0eba9cd3dda8dfb7e7dae" @@ -9673,7 +9791,7 @@ react-testing-library@^8.0.1: resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-8.0.1.tgz#b3dd43bce3fa88423cf0a23292fb819023c227cc" integrity sha512-Gq4JC9r3prA4hYwo7afcbHHMFckO29+5Nrh2KblAEPuK/DWaU0bJE1vtpAgLhzhY9bBirmcgjjIHljHEwGAXKw== -react-transition-group@^4.3.0: +react-transition-group@^4.0.0, react-transition-group@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683" integrity sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw== @@ -10128,7 +10246,14 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2.7.1: +rifm@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.7.0.tgz#debe951a9c83549ca6b33e5919f716044c2230be" + integrity sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ== + dependencies: + "@babel/runtime" "^7.3.1" + +rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -10244,7 +10369,7 @@ sass-loader@7.3.1: pify "^4.0.1" semver "^6.3.0" -sax@^1.2.4, sax@~1.2.4: +sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -11783,10 +11908,10 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validator@^12.0.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-12.2.0.tgz#660d47e96267033fd070096c3b1a6f2db4380a0a" - integrity sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ== +validator@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.0.0.tgz#0fb6c6bb5218ea23d368a8347e6d0f5a70e3bcab" + integrity sha512-anYx5fURbgF04lQV18nEQWZ/3wHGnxiKdG4aL8J+jEDsm98n/sU/bey+tYk6tnGJzm7ioh5FoqrAiQ6m03IgaA== value-equal@^1.0.1: version "1.0.1" @@ -12190,6 +12315,19 @@ xregexp@^4.3.0: dependencies: "@babel/runtime-corejs3" "^7.8.3" +xml2js@^0.4.17: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"