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

DTL (Test > Levelbuilder): 24d77bd3 #35152

Merged
merged 23 commits into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
16e132e
Constrain AnimationPicker dialog width
May 28, 2020
9def96c
add setup to reserved words
ajpal May 29, 2020
020dff0
Allow third option for virtual workshops
bencodeorg Jun 3, 2020
4c7b2c1
Friday Institute workshops must be virtual
bencodeorg Jun 3, 2020
1ec9957
Add workshop model tests
bencodeorg Jun 3, 2020
415675b
Updates to Students Grades 6-12 page
breville Jun 3, 2020
838039e
Update options for virtual workshops
bencodeorg Jun 3, 2020
81fd541
fix editor bug
molly-moen Jun 3, 2020
28660c9
fixed brokenness
JillianK Jun 3, 2020
1328a67
Student 6-12 page: update Lab blocks
breville Jun 3, 2020
86a9a3c
Student 6-12 page: fix box heights
breville Jun 3, 2020
f228caa
Merge pull request #35039 from code-dot-org/may29-spritelab-setup
ajpal Jun 4, 2020
2c0f3d8
Merge pull request #35132 from code-dot-org/staging
deploy-code-org Jun 4, 2020
0e85d88
Merge pull request #35130 from code-dot-org/appplab-camera-integratio…
JillianK Jun 4, 2020
7836d66
Merge pull request #35133 from code-dot-org/staging
deploy-code-org Jun 4, 2020
cccdb2e
Student 6-12 page: code review feedback
breville Jun 4, 2020
712cc3c
Merge pull request #35120 from code-dot-org/third-virtual-option
bencodeorg Jun 4, 2020
d3f3519
Merge pull request #35136 from code-dot-org/staging
deploy-code-org Jun 4, 2020
d2115a7
Merge pull request #35129 from code-dot-org/molly/fix-editor-bug
molly-moen Jun 4, 2020
1d30a8c
Merge pull request #35118 from code-dot-org/student-middle-high-updates
breville Jun 4, 2020
2baf565
Merge pull request #35140 from code-dot-org/staging
deploy-code-org Jun 4, 2020
f34ce53
Merge pull request #35024 from code-dot-org/scroll-bug
Jun 4, 2020
24d77bd
Merge pull request #35144 from code-dot-org/staging
deploy-code-org Jun 4, 2020
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
2 changes: 1 addition & 1 deletion apps/src/applab/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ applabCommands.getImageURL = function(opts) {
return element.getAttribute('data-canonical-image-url');
} else if (
element.tagName === 'LABEL' &&
element.className === 'img-upload'
$(element).hasClass('img-upload')
) {
var fileObj = element.children[0].files[0];
if (fileObj) {
Expand Down
2 changes: 1 addition & 1 deletion apps/src/applab/designElements/photoSelect.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export default {
onDeserialize: function(element, updateProperty) {
// Disable image upload events unless running
$(element).on('click', () => {
element.childNodes[0] = !Applab.isRunning();
element.childNodes[0].disabled = !Applab.isRunning();
});
}
};
2 changes: 1 addition & 1 deletion apps/src/code-studio/pd/foorm/FoormEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class FoormEditor extends React.Component {
type="text"
value={this.state.workshop_subject}
onChange={e =>
this.setState({workshop_course: e.target.value})
this.setState({workshop_subject: e.target.value})
}
/>
</label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ const placeholderSession = {
endTime: '5:00pm'
};

// When selecting whether a workshop is virtual through the UI,
// a user is really selecting two things:
// a) whether the workshop is occurring virtually, and
// b) if there's a third party responsible for the content/structure of the workshop.
// These two things are stored as separate attributes in the workshop model.
const virtualWorkshopTypes = ['regional', 'friday_institute'];
const thirdPartyProviders = ['friday_institute'];

export class WorkshopForm extends React.Component {
static contextTypes = {
router: PropTypes.object.isRequired
Expand All @@ -78,7 +86,7 @@ export class WorkshopForm extends React.Component {
id: PropTypes.number.isRequired,
facilitators: PropTypes.array.isRequired,
location_name: PropTypes.string.isRequired,
location_address: PropTypes.string.isRequired,
location_address: PropTypes.string,
capacity: PropTypes.number.isRequired,
on_map: PropTypes.bool.isRequired,
funded: PropTypes.bool.isRequired,
Expand All @@ -92,6 +100,7 @@ export class WorkshopForm extends React.Component {
regional_partner_name: PropTypes.string,
regional_partner_id: PropTypes.number,
virtual: PropTypes.bool,
third_party_provider: PropTypes.string,
suppress_email: PropTypes.bool,
organizer: PropTypes.shape({
id: PropTypes.number,
Expand Down Expand Up @@ -131,7 +140,8 @@ export class WorkshopForm extends React.Component {
showTypeOptionsHelpDisplay: false,
regional_partner_id: '',
virtual: false,
suppress_email: false
suppress_email: false,
third_party_provider: null
};

if (props.workshop) {
Expand All @@ -152,7 +162,8 @@ export class WorkshopForm extends React.Component {
'regional_partner_id',
'organizer',
'virtual',
'suppress_email'
'suppress_email',
'third_party_provider'
])
);
initialState.sessions = this.prepareSessionsForForm(
Expand Down Expand Up @@ -737,13 +748,33 @@ export class WorkshopForm extends React.Component {
return value;
};

currentVirtualStatus = () => {
const {virtual, third_party_provider} = this.state;

// First, check if the third party provider is a valid
// virtual workshop type.
if (virtualWorkshopTypes.includes(third_party_provider)) {
return third_party_provider;
} else if (virtual) {
return 'regional';
} else {
return 'in_person';
}
};

handleVirtualChange = event => {
// This field gets its own handler both so we can coerce its value to
// boolean, and so we can enforce some business logic that says:
// Virtual workshops ALWAYS suppress email.
const virtual = event.target.value === 'true';
const value = event.target.value;
const virtual = virtualWorkshopTypes.includes(value);
const suppress_email = virtual || this.state.suppress_email;
this.setState({virtual, suppress_email});

this.setState({
virtual,
suppress_email,
third_party_provider: thirdPartyProviders.includes(value) ? value : null
});
};

handleSuppressEmailChange = event => {
Expand Down Expand Up @@ -812,6 +843,7 @@ export class WorkshopForm extends React.Component {
notes: this.state.notes,
virtual: this.state.virtual,
suppress_email: this.state.suppress_email,
third_party_provider: this.state.third_party_provider,
sessions_attributes: this.prepareSessionsForApi(
this.state.sessions,
this.state.destroyedSessions
Expand Down Expand Up @@ -1011,7 +1043,7 @@ export class WorkshopForm extends React.Component {
</HelpTip>
</ControlLabel>
<SelectIsVirtual
value={this.state.virtual || false}
value={this.currentVirtualStatus()}
onChange={this.handleVirtualChange}
readOnly={this.props.readOnly}
/>
Expand Down Expand Up @@ -1179,16 +1211,19 @@ const SelectIsVirtual = ({value, readOnly, onChange}) => (
style={readOnly ? styles.readOnlyInput : undefined}
disabled={readOnly}
>
<option key={false} value={false}>
<option key={'in_person'} value={'in_person'}>
No, this is an in-person workshop.
</option>
<option key={true} value={true}>
Yes, this is a virtual workshop.
<option key={'friday_institute'} value={'friday_institute'}>
Yes, this is a Code.org-Friday Institute virtual workshop.
</option>
<option key={'regional'} value={'regional'}>
Yes, this is a regional virtual workshop.
</option>
</FormControl>
);
SelectIsVirtual.propTypes = {
value: PropTypes.bool.isRequired,
value: PropTypes.string.isRequired,
readOnly: PropTypes.bool,
onChange: PropTypes.func.isRequired
};
Expand Down
3 changes: 2 additions & 1 deletion apps/src/code-studio/pd/workshop_dashboard/workshop.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ export class Workshop extends React.Component {
'potential_organizers',
'created_at',
'virtual',
'suppress_email'
'suppress_email',
'third_party_provider'
])
});
})
Expand Down
1 change: 1 addition & 0 deletions apps/src/p5lab/AnimationPicker/AnimationPicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class AnimationPicker extends React.Component {
handleClose={this.props.onClose}
uncloseable={this.props.uploadInProgress}
fullWidth={true}
style={styles.dialog}
>
<HiddenUploader
ref="uploader"
Expand Down
10 changes: 10 additions & 0 deletions apps/src/p5lab/AnimationPicker/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
var color = require('@cdo/apps/util/color');

module.exports = {
dialog: {
/**
* Constrain the width of the dialog so that it is always vertically scrollable,
* which is necessary for infinite scroll to work.
* https://github.com/code-dot-org/code-dot-org/pull/34463
*/
maxWidth: 1000,
marginLeft: 0,
transform: 'translate(-50%, 0)'
},
title: {
color: color.purple,
textAlign: 'center',
Expand Down
1 change: 1 addition & 0 deletions apps/src/p5lab/spritelab/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports.SpritelabReservedWords = [
'text',
'textAlign',
'textSize',
'setup',
// NativeSpriteLab.interpreted.js
'extraArgs',
'draw',
Expand Down
20 changes: 2 additions & 18 deletions apps/src/sites/code.org/pages/public/student/middle-high.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';

import MiddleHighResourceCards from './MiddleHighResourceCards';
import initResponsive from '@cdo/apps/code-studio/responsive';
import isRtl from '@cdo/apps/code-studio/isRtlRedux';
import responsive from '@cdo/apps/code-studio/responsiveRedux';
import {getStore, registerReducers} from '@cdo/apps/redux';

registerReducers({isRtl, responsive});

document.addEventListener('DOMContentLoaded', () => {
$(document).ready(function() {
initResponsive();

const container = document.getElementById('educate-resources-grid');
ReactDOM.render(
<Provider store={getStore()}>
<MiddleHighResourceCards />
</Provider>,
container
);
$('.hoc-tiles-container').load('/dashboardapi/middle_high_student_labs');
});
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ def workshop_params(can_update_regional_partner = true)
:organizer_id,
:virtual,
:suppress_email,
:third_party_provider,
sessions_attributes: [:id, :start, :end, :_destroy],
]

Expand Down
9 changes: 9 additions & 0 deletions dashboard/app/helpers/course_block_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ def self.get_tall_course_block(id, family_name = nil)
url: CDO.code_org_url('/educate/applab'),
body: I18n.t('upsell.applab.body_short')
},
'gamelab' => {
url: CDO.code_org_url('/educate/gamelab'),
body: I18n.t('upsell.gamelab.body')
},
'weblab' => {
url: CDO.code_org_url('/educate/weblab'),
title: "Web Lab",
body: I18n.t('upsell.weblab.body')
},
'conditionals' => {
url: CDO.code_org_url('/hourofcode/unplugged-conditionals-with-cards'),
title: I18n.t('upsell.unplugged_conditionals.title'),
Expand Down
16 changes: 16 additions & 0 deletions dashboard/app/models/pd/workshop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ class Pd::Workshop < ActiveRecord::Base
# - Uses a different, virtual-specific post-workshop survey.
'virtual',

# Allows a workshop to be associated with a third party
# organization.
# Only current allowed values are "friday_institute" and nil.
# "friday_institute" represents The Friday Institute,
# a regional partner whose model of virtual workshop is being used
# by several partners during summer 2020.
'third_party_provider',

# If true, our system will not send enrollee-facing
# emails related to this workshop *except* for a receipt for the teacher
# if they cancel their enrollment and the post-workshop survey,
Expand All @@ -84,6 +92,8 @@ class Pd::Workshop < ActiveRecord::Base
validates_inclusion_of :on_map, in: [true, false]
validates_inclusion_of :funded, in: [true, false]
validate :all_virtual_workshops_suppress_email
validates_inclusion_of :third_party_provider, in: %w(friday_institute), allow_nil: true
validate :friday_institute_workshops_must_be_virtual

validates :funding_type,
inclusion: {in: FUNDING_TYPES, if: :funded_csf?},
Expand Down Expand Up @@ -119,6 +129,12 @@ def all_virtual_workshops_suppress_email
end
end

def friday_institute_workshops_must_be_virtual
if third_party_provider == 'friday_institute' && !virtual?
errors.add :properties, 'Friday Institute workshops must be virtual'
end
end

def self.organized_by(organizer)
where(organizer_id: organizer.id)
end
Expand Down
2 changes: 1 addition & 1 deletion dashboard/app/serializers/api/v1/pd/workshop_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Api::V1::Pd::WorkshopSerializer < ActiveModel::Serializer
:enrolled_teacher_count, :sessions, :account_required_for_attendance?,
:enrollment_code, :pre_workshop_survey_url, :attended, :on_map, :funded, :funding_type, :ready_to_close?,
:workshop_starting_date, :date_and_location_name, :regional_partner_name, :regional_partner_id,
:scholarship_workshop?, :can_delete, :created_at, :virtual, :suppress_email
:scholarship_workshop?, :can_delete, :created_at, :virtual, :suppress_email, :third_party_provider

def sessions
object.sessions.map do |session|
Expand Down
4 changes: 4 additions & 0 deletions dashboard/app/views/api/middle_high_student_labs.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.row{style: "margin: 0;"}
= render partial: 'shared/course_tall_block', locals: { id: 'applab' }
= render partial: 'shared/course_tall_block', locals: { id: 'gamelab' }
= render partial: 'shared/course_tall_block', locals: { id: 'weblab' }
17 changes: 17 additions & 0 deletions dashboard/test/models/pd/workshop_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1347,6 +1347,23 @@ class Pd::WorkshopTest < ActiveSupport::TestCase
assert workshop.valid?
end

test 'friday_institute workshops must be virtual' do
workshop = build :workshop, third_party_provider: 'friday_institute', virtual: false
refute workshop.valid?

workshop.virtual = true
workshop.suppress_email = true
assert workshop.valid?
end

test 'workshops third_party_provider must be nil or from specified list' do
workshop = build :workshop, third_party_provider: 'unknown_pd_provider'
refute workshop.valid?

workshop.third_party_provider = nil
assert workshop.valid?
end

private

def session_on_day(day_offset)
Expand Down