Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DTT (Staging > Test) [robo-dtt] #25041

Merged
merged 27 commits into from Sep 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
336b307
Add teacher1920 application email support: enable cc, add new copy, a…
Sep 21, 2018
4cf1798
Update models and fix tests
Sep 23, 2018
3046ec8
Update eyes tests
Sep 23, 2018
9584f90
Ensure regional partner in UI test
Sep 23, 2018
b6ebe3c
Enumerate application statuses from server data rather than client co…
Sep 24, 2018
1adc3b1
s/invoiced/paid
Sep 24, 2018
f5456e7
add display name to user account dropdown
Erin007 Sep 25, 2018
b5a6062
use short_name data directly
Erin007 Sep 25, 2018
1b31cef
Fix constant typo, and attmept to fix test
Sep 25, 2018
29e47bd
PL regional partner search: search by ZIP only & geocode to find stat…
breville Sep 25, 2018
0793b6c
Add id to submit button, try to fix failing UI test
Sep 25, 2018
f3c65e4
remove icons from the bottom of the personal projects page
Erin007 Sep 25, 2018
c2f2b1f
Merge remote-tracking branch 'origin/staging' into teacher-applicatio…
Sep 25, 2018
52c1ddc
More email updates and fixes
Sep 26, 2018
d500b77
use locale rather than request.language to set the language selector …
Erin007 Sep 26, 2018
578c84c
Merge branch 'staging' into teacher-application-emails
Sep 26, 2018
2255ee9
PR feedback
Sep 26, 2018
71a8ac8
Merge pull request #25011 from code-dot-org/regional-partner-search-z…
breville Sep 26, 2018
89084af
PL regional partner search: refinements
breville Sep 26, 2018
9f360a9
Fix principal approval receipt email
Sep 26, 2018
3141d20
Merge pull request #25027 from code-dot-org/es-mx-vs-es-es
Erin007 Sep 26, 2018
a78cd59
Merge branch 'staging' into remove-project-cards
Erin007 Sep 26, 2018
e89f76e
Merge pull request #25004 from code-dot-org/display-name-in-user-drop…
Erin007 Sep 26, 2018
dedd6e4
Merge pull request #24950 from code-dot-org/teacher-application-emails
aoby Sep 26, 2018
0054ea4
Updated cookbook versions
deploy-code-org Sep 26, 2018
d0a6de7
Merge pull request #25034 from code-dot-org/regional-partner-search-r…
breville Sep 26, 2018
60b8ad4
Merge pull request #25017 from code-dot-org/remove-project-cards
Erin007 Sep 26, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 22 additions & 33 deletions apps/src/code-studio/pd/application_dashboard/summary_table.jsx
Expand Up @@ -31,14 +31,9 @@ export class SummaryTable extends React.Component {
static propTypes = {
showLocked: PropTypes.bool,
caption: PropTypes.string.isRequired,
data: PropTypes.shape({
accepted: ApplicationDataPropType,
declined: ApplicationDataPropType,
interview: ApplicationDataPropType,
pending: ApplicationDataPropType,
unreviewed: ApplicationDataPropType,
waitlisted: ApplicationDataPropType,
}),

// keys are available statuses: {status: ApplicationDataPropType}
data: PropTypes.objectOf(ApplicationDataPropType),
path: PropTypes.string.isRequired,
id: PropTypes.string
};
Expand All @@ -48,21 +43,19 @@ export class SummaryTable extends React.Component {
};

tableBody() {
return Object.keys(StatusColors).map((status, i) => {
if (this.props.data.hasOwnProperty(status)) {
const data = this.props.data[status];
const total = data.locked + data.unlocked;
return (
<tr key={i}>
<td style={{...styles.statusCell[status]}}>
{_.upperFirst(status)}
</td>
{this.props.showLocked && <td>{data.locked}</td>}
{this.props.showLocked && <td>{data.unlocked}</td>}
<td>{total}</td>
</tr>
);
}
return Object.keys(this.props.data).map((status, i) => {
const statusData = this.props.data[status];
const total = statusData.locked + statusData.unlocked;
return (
<tr key={i}>
<td style={{...styles.statusCell[status]}}>
{_.upperFirst(status)}
</td>
{this.props.showLocked && <td>{statusData.locked}</td>}
{this.props.showLocked && <td>{statusData.unlocked}</td>}
<td>{total}</td>
</tr>
);
});
}

Expand Down Expand Up @@ -105,16 +98,12 @@ export class SummaryTable extends React.Component {
>
View all applications
</Button>
{
this.props.data.accepted.locked + this.props.data.accepted.unlocked > 0 && (
<Button
href={this.context.router.createHref(`/${this.props.path}_cohort`)}
onClick={this.handleViewCohortClick}
>
View accepted cohort
</Button>
)
}
<Button
href={this.context.router.createHref(`/${this.props.path}_cohort`)}
onClick={this.handleViewCohortClick}
>
View accepted cohort
</Button>
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions apps/src/code-studio/pd/form_components/FormController.jsx
Expand Up @@ -441,6 +441,7 @@ export default class FormController extends React.Component {
bsStyle="primary"
disabled={this.state.submitting}
key="submit"
id="submit"
type="submit"
>
{this.constructor.submitButtonText}
Expand Down
5 changes: 1 addition & 4 deletions apps/src/regionalPartnerSearch/regionalPartnerSearch.js
Expand Up @@ -14,13 +14,10 @@ $(document).ready(initRegionalPartnerSearch);

function showRegionalPartnerSearch() {
const regionalPartnerSearchElement = $('#regional-partner-search');
const states = regionalPartnerSearchElement.data("states");

ReactDOM.render(
<Provider store={getStore()}>
<RegionalPartnerSearch
states={states}
/>
<RegionalPartnerSearch/>
</Provider>,
regionalPartnerSearchElement[0]
);
Expand Down
127 changes: 66 additions & 61 deletions apps/src/templates/RegionalPartnerSearch.jsx
@@ -1,51 +1,50 @@
import React, { PropTypes, Component } from 'react';
import { connect } from 'react-redux';
import {WorkshopApplicationStates} from '@cdo/apps/generated/pd/sharedWorkshopConstants';

import UnsafeRenderedMarkdown from '@cdo/apps/templates/UnsafeRenderedMarkdown';
import $ from 'jquery';

const styles = {
heading: {
marginBottom: 5
},
form: {
marginTop: 20
},
schoolZipLabel: {
width: 150,
},
zipSubmit: {
marginTop: 20
},
noPartner: {
marginTop: 20
},
workshop: {
marginBottom: 20
}
};

class RegionalPartnerSearch extends Component {
static propTypes = {
responsiveSize: PropTypes.oneOf(['lg', 'md', 'sm', 'xs']).isRequired,
states: PropTypes.arrayOf(PropTypes.array)
responsiveSize: PropTypes.oneOf(['lg', 'md', 'sm', 'xs']).isRequired
};

state = {
partnerInfo: undefined,
stateValue: "",
zipValue: "",
allowZip: false,
noPartner: false
};

workshopSuccess = (response) => {
this.setState({partnerInfo: response });
};

workshopFail = (response) => {
this.setState({allowZip: true});
};

workshopZipFail = (response) => {
this.setState({noPartner: true});
};

handleStateChange = (e) => {
this.setState({
stateValue: e.target.value,
zipValue: "",
allowZip: false,
partnerInfo: undefined,
noPartner: false
});

$.ajax({
url: "/dashboardapi/v1/regional_partners/find?state=" + e.target.value,
type: "get",
dataType: "json"
}).done(this.workshopSuccess).fail(this.workshopFail);
};

handleZipChange = (event) => {
this.setState({zipValue: event.target.value});
};
Expand Down Expand Up @@ -79,40 +78,43 @@ class RegionalPartnerSearch extends Component {
const appState = partnerInfo && partnerInfo.application_state.state;
const appsOpenDate = partnerInfo && partnerInfo.application_state.earliest_open_date;

const applicationLink = (partnerInfo && partnerInfo.link_to_partner_application) ||
"https://studio.code.org/pd/application/teacher";
let applicationLink, applicationLinkTarget;
if (partnerInfo && partnerInfo.link_to_partner_application) {
applicationLink = partnerInfo.link_to_partner_application;
applicationLinkTarget = "_blank";
} else {
applicationLink = "https://studio.code.org/pd/application/teacher";
applicationLinkTarget = null;
}

return (
<div>
<h2>Ready to apply?</h2>
School State:
<select value={this.state.stateValue} onChange={this.handleStateChange} style={{width: '150px'}}>
<option disabled value=""/>
{this.props.states.map(item => {
return <option key={item[0]} value={item[0]}>{item[1]}</option>;
})}
</select>

{this.state.allowZip && (
<form onSubmit={this.handleZipSubmit}>
<label>
School Zip Code:
<input type="text" value={this.state.zipValue} onChange={this.handleZipChange} />
</label>
<div>
<input type="submit" value="Submit" />
</div>
</form>
)}
<h2 style={styles.heading}>Ready to apply?</h2>
<div>Our Regional Partners offer local workshops throughout the United States. Enter your location to find a workshop near you.</div>

<form onSubmit={this.handleZipSubmit} style={styles.form}>
<label style={styles.schoolZipLabel}>School Zip Code:</label>
<input type="text" value={this.state.zipValue} onChange={this.handleZipChange} />
<div style={styles.zipSubmit}>
<input type="submit" value="Submit" />
</div>
</form>

{this.state.noPartner || partnerInfo && (
<h3>Regional Partner hosting the Professional Development Program in this region:</h3>
<h3>Code.org Regional Partner for your region:</h3>
)}

{this.state.noPartner && (
<div>
<div>There is no Regional Partner in your region. While we cannot guarantee availability, you can still apply should a space in a nearby region become available.</div>
<div>Applications open January 15, 2019</div>
<div style={styles.noPartner}>
<p>We do not yet have a Regional Partner in your area. However, we have a number of partners in nearby states or regions who may have space available in their program. If you are willing to travel, please fill out the application. We'll let you know if we can find you a nearby spot in the program!</p>
<p>If we find a spot, we'll let you know the workshop dates and program fees (if applicable) so you can decide at that point if it is something your school can cover.</p>
<p>
All of our curriculum, tools, and courses are also available for your school at no cost.
{' '}
<a href="https://code.org/educate/curriculum/3rd-party">Or, contact one of these computer science providers</a>
{' '}
for other Professional Development options in your area.</p>
<p>Applications open January 15, 2019.</p>
</div>
)}

Expand All @@ -133,34 +135,37 @@ class RegionalPartnerSearch extends Component {
</div>
)}

<h3>Summer workshop(s):</h3>
<h3>Workshop information:</h3>
{workshopCollections[0].workshops.length === 0 && workshopCollections[1].workshops.length === 0 && (
<div>Summer workshop dates and locations are TBD</div>
<div>Workshop date and location information coming soon.</div>
)}

{workshopCollections.map((collection, collectionIndex) => collection.workshops.length > 0 && (
<div key={collectionIndex}>
<h4>{collection.heading}</h4>
{collection.workshops.map((workshop, index) => (
<div key={index}>
<div key={index} style={styles.workshop}>
<div>{workshop.workshop_date_range_string}</div>
<div>{workshop.location_name}</div>
<div>{workshop.location_address}</div>
</div>
))}
</div>
))}
<div>In addition to the summer workshop, the professional learning program includes 4 workshops (dates TBD) and online support throughout the the year.</div>

<h3>Cost and scholarship information:</h3>
<div>In addition to attending a five-day summer workshop, the professional learning program includes up to 4 one-day, in-person academic year workshops during the 2019-20 school year. Academic year workshop dates will be finalized and shared by your Regional Partner.</div>

{partnerInfo.cost_scholarship_information && (
<div>{partnerInfo.cost_scholarship_information}</div>
<div>
<h3>Cost and scholarship information:</h3>
<UnsafeRenderedMarkdown markdown={partnerInfo.cost_scholarship_information}/>
</div>
)}

{partnerInfo.additional_program_information && (
<div>
<h3>Additional Program Information:</h3>
<div>{partnerInfo.additional_program_information}</div>
<h3>Additional program information:</h3>
<UnsafeRenderedMarkdown markdown={partnerInfo.additional_program_information}/>
</div>
)}

Expand All @@ -169,18 +174,18 @@ class RegionalPartnerSearch extends Component {
)}

{appState === WorkshopApplicationStates.currently_open && (
<a href={applicationLink}>
<a href={applicationLink} target={applicationLinkTarget}>
<button>Start application</button>
</a>
)}

{appState === WorkshopApplicationStates.opening_at && (
<div>Applications open {appsOpenDate}</div>
<div>Applications will open on {appsOpenDate}.</div>
)}

{appState === WorkshopApplicationStates.opening_sometime && (
<div>
<div>Applications will be open soon.</div>
<h3>Program information and the application for this region will be available soon!</h3>
<a href="https://studio.code.org/pd/regional_partner_contact/new">
<button>
Tell me when applications open
Expand Down
5 changes: 4 additions & 1 deletion apps/src/templates/projects/PersonalProjectsTable.jsx
Expand Up @@ -74,6 +74,9 @@ export const styles = {
justifyContent: 'center',
alignItems: 'center',
},
bottomMargin: {
marginBottom: 20
}
};

// Cell formatters.
Expand Down Expand Up @@ -296,7 +299,7 @@ class PersonalProjectsTable extends React.Component {
const noProjects = this.props.personalProjectsList.length === 0;

return (
<div>
<div style={styles.bottomMargin}>
{!noProjects &&
<Table.Provider
columns={columns}
Expand Down
2 changes: 1 addition & 1 deletion cookbooks/Berksfile.lock
Expand Up @@ -73,7 +73,7 @@ GRAPH
cdo-analytics (0.0.0)
apt (~> 2.6.0)
ark (>= 0.0.0)
cdo-apps (0.2.319)
cdo-apps (0.2.320)
apt (>= 0.0.0)
build-essential (>= 0.0.0)
cdo-analytics (>= 0.0.0)
Expand Down
2 changes: 1 addition & 1 deletion cookbooks/cdo-apps/metadata.rb
Expand Up @@ -4,7 +4,7 @@
license 'All rights reserved'
description 'Installs/Configures cdo-apps'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.2.319'
version '0.2.320'

depends 'apt'
depends 'build-essential'
Expand Down
2 changes: 1 addition & 1 deletion cookbooks/cdo-apps/templates/default/crontab.erb
Expand Up @@ -83,7 +83,7 @@
cronjob at:'20 */4 * * *', do:deploy_dir('bin', 'cron', 'activity-monitor')
cronjob at:'15 16 * * *', do:dashboard_dir('bin','scheduled_ops_emails')
cronjob at:'30 14 * * *', do:dashboard_dir('bin','scheduled_pd_workshop_emails')
cronjob at:'0 14 * * 1', do:dashboard_dir('bin','scheduled_pd_application_emails')
cronjob at:'0 16 * * *', do:dashboard_dir('bin','scheduled_pd_application_emails')
cronjob at:'10 */12 * * *', do:dashboard_dir('bin','refresh_pd_workshop_material_orders')
cronjob at:'*/1 * * * *', do:dashboard_dir('bin', 'fill_jotform_placeholders')
cronjob at:'30 0 * * *', do:dashboard_dir('bin', 'sync_jotforms')
Expand Down
Expand Up @@ -38,12 +38,9 @@ def on_successful_create
can_pay_fee: principal_response[:pay_fee]
}
)
teacher_application.save
teacher_application.save!
teacher_application.auto_score!

TEACHER_APPLICATION_MAILER_CLASS.principal_approval_received(
@application.teacher_application
).deliver_now
teacher_application.queue_email(:principal_approval_completed, deliver_now: true)
end
end
end
Expand Up @@ -12,17 +12,19 @@ def new_form
end

def resend_principal_approval
PRINCIPAL_APPROVAL_APPLICATION_CLASS.create_placeholder_and_send_mail(
TEACHER_APPLICATION_CLASS.find(params[:id])
)
application = TEACHER_APPLICATION_CLASS.find(params[:id])
application.queue_email :principal_approval, deliver_now: true
end

protected

def on_successful_create
@application.update_user_school_info!
@application.queue_email :confirmation, deliver_now: true

TEACHER_APPLICATION_MAILER_CLASS.confirmation(@application).deliver_now
unless @application.regional_partner&.applications_principal_approval == RegionalPartner::SELECTIVE_APPROVAL
@application.queue_email :principal_approval, deliver_now: true
end
end
end
end