Skip to content

Commit

Permalink
Merge pull request #57619 from code-dot-org/dtp_candidate_f2b11bec
Browse files Browse the repository at this point in the history
DTP (Test > Production: f2b11be)
  • Loading branch information
bencodeorg committed Mar 28, 2024
2 parents b33d8b3 + f2b11be commit 7e8afbe
Show file tree
Hide file tree
Showing 382 changed files with 41,819 additions and 1,398 deletions.
18 changes: 10 additions & 8 deletions .drone.yml
@@ -1,6 +1,6 @@
---
# Drone CI pipeline running at: https://drone.cdn-code.org/code-dot-org/code-dot-org/
#
#
# Docs here: https://docs.google.com/document/d/1Qls20xfNN6T_DErOMwVQOFJsxAEAdMWFHzBDIbxyUQQ/edit#heading=h.9bln2fv2lgqd
#
# NOTE: after making changes to this file, you'll need to sign them using
Expand Down Expand Up @@ -111,8 +111,10 @@ volumes:

trigger:
branch:
- "staging"
- "staging-next"
exclude:
- "production"
- "test"
- "levelbuilder"
event:
- pull_request

Expand Down Expand Up @@ -242,13 +244,14 @@ volumes:

trigger:
branch:
- "staging"
- "staging-next"
exclude:
- "production"
- "test"
- "levelbuilder"
event:
- pull_request

---

# On push, cache a clone of staging to drone's S3 bucket.
# The staging cache reduces git bandwidth in PR pipelines.
kind: pipeline
Expand All @@ -259,7 +262,6 @@ clone:
disable: true

steps:

- name: clone
image: bitnami/git
commands:
Expand All @@ -285,6 +287,6 @@ trigger:
- push
---
kind: signature
hmac: a16fa2865512ffb9127b4d8a311fa8fdc078145723a8aa2767bea7cce97c1ed5
hmac: e51f14b739c978b477222c272341dc9552ad743ee7658a48cf75ee5d5b976d7f

...
7 changes: 4 additions & 3 deletions apps/i18n/common/en_us.json
Expand Up @@ -1602,6 +1602,7 @@
"low": "low",
"ltiSectionSyncButtonDisabledAltText": "Roster sync is disabled. To re-enable, go to your account settings.",
"ltiSectionSyncDialogDescription": "New to Code.org? A [section]({aboutSectionsUrl}) is used to manage your classroom and assign curricula. We've identified the following sections & students associated with your course.\n\nYou can re-sync your sections & students at any time! Learn more [about syncing here]({aboutSyncingUrl}).",
"ltiSectionSyncDialogDescriptionNoChange": "You're all set! Your sections & students are already up to date.\n\nYou can re-sync your sections at any time. Learn more [about syncing here]({aboutSyncingUrl})",
"ltiSectionSyncDialogError": "We encountered an error when trying to sync with your LMS.",
"ltiSectionSyncDialogErrorNoIntegration": "LTI Integration not found",
"ltiSectionSyncDialogErrorNoSectionFound": "We couldn't find the given section.",
Expand Down Expand Up @@ -2220,9 +2221,9 @@
"rubricLevelFourHeader": "No Evidence",
"rubricScores": "Rubric Scores",
"rubricAiHeaderText": "AI Teaching Assistant",
"rubricTabStudent": "Student Rubric",
"rubricTabClassManagement": "Class Management",
"rubricNoStudentEvals": "You haven't evaluated any student work yet. Switch to the Student Rubric view and then use the dropdown menu to choose a student to evaluate.",
"rubricTabStudent": "Assess a Student",
"rubricTabClassManagement": "Class Data",
"rubricNoStudentEvals": "You haven't evaluated any student work yet. Switch to the 'Assess a Student' tab and then use the dropdown menu to choose a student to evaluate.",
"rubricNumberStudentEvals": "You have evaluated this lesson for {teacherEvalCount} students.",
"rubricViewStudentRubric": "View Student Rubric",
"rubricSummaryClassScore": "Summary of Class Scores",
Expand Down
43 changes: 43 additions & 0 deletions apps/src/blockly/addons/cdoUtils.ts
Expand Up @@ -31,6 +31,7 @@ import {Block, BlockSvg, Field, Theme, WorkspaceSvg} from 'blockly';
import {BlockColor, JsonBlockConfig, WorkspaceSerialization} from '../types';
import experiments from '@cdo/apps/util/experiments';
import {getBaseName} from '../utils';
import {ToolboxItemInfo} from 'blockly/core/utils/toolbox';

/**
* Loads blocks to a workspace.
Expand Down Expand Up @@ -58,6 +59,48 @@ export function loadBlocksToWorkspace(
Blockly.serialization.workspaces.load(mainSource, workspace);
positionBlocksOnWorkspace(workspace);
Blockly.hasLoadedBlocks = true;

// Dynamically add procedure call blocks to an uncategorized toolbox
// if specified in the level config (e.g. Minecraft Agent levels).
// Levels will include: "top_level_procedure_autopopulate": "true"
if (Blockly.topLevelProcedureAutopopulate) {
addProcedureCallBlocksToFlyout(workspace, mainSource);
}
}

function addProcedureCallBlocksToFlyout(
workspace: WorkspaceSvg,
mainSource: WorkspaceSerialization
) {
// options.languageTree is the translated toolbox info
if (workspace.getFlyout() && workspace.options?.languageTree) {
const callBlocks = [] as ToolboxItemInfo[];
const defBlocks = mainSource.blocks.blocks.filter(
block => block.type === 'procedures_defnoreturn'
);
defBlocks.forEach(def => {
// Procedure definitions should have a valid name
if (typeof def.fields?.NAME === 'string') {
// Create the block XML for a procedure call block.
const block = document.createElement('block');
block.setAttribute('type', 'procedures_callnoreturn');
const mutation = document.createElement('mutation');
mutation.setAttribute('name', def.fields.NAME);
block.appendChild(mutation);

callBlocks.push({
kind: 'BLOCK',
blockxml: block,
type: 'procedures_callnoreturn',
});
}
});
if (callBlocks.length) {
// Add the new callblocks to the toolbox and refresh it.
workspace.options.languageTree.contents.push(...callBlocks);
workspace.getFlyout()?.show(workspace.options.languageTree);
}
}
}

/**
Expand Down
3 changes: 3 additions & 0 deletions apps/src/blockly/googleBlocklyWrapper.ts
Expand Up @@ -729,6 +729,9 @@ function initializeBlocklyWrapper(blocklyInstance: GoogleBlocklyInstance) {
options
) as ExtendedWorkspaceSvg;

blocklyWrapper.topLevelProcedureAutopopulate =
!!options.topLevelProcedureAutopopulate;

if (options.noFunctionBlockFrame) {
workspace.noFunctionBlockFrame = options.noFunctionBlockFrame;
}
Expand Down
2 changes: 2 additions & 0 deletions apps/src/blockly/types.ts
Expand Up @@ -67,6 +67,7 @@ type GoogleBlocklyType = typeof GoogleBlockly;

// Type for the Blockly instance created and modified by googleBlocklyWrapper.
export interface BlocklyWrapperType extends GoogleBlocklyType {
topLevelProcedureAutopopulate: boolean;
getNewCursor: (type: string) => Cursor;
LineCursor: typeof GoogleBlockly.BasicCursor;
version: BlocklyVersion;
Expand Down Expand Up @@ -217,6 +218,7 @@ export interface ExtendedBlocklyOptions extends BlocklyOptions {
levelBlockIds: string[];
isBlockEditMode: boolean;
editBlocks: string | undefined;
topLevelProcedureAutopopulate: boolean | undefined;
noFunctionBlockFrame: boolean;
useModalFunctionEditor: boolean;
useBlocklyDynamicCategories: boolean;
Expand Down
2 changes: 1 addition & 1 deletion apps/src/lib/ui/lti/sync/LtiSectionSyncDialog.story.tsx
Expand Up @@ -37,7 +37,7 @@ SuccessfulSync.args = {
size: 32,
},
},
updated: {
changed: {
2: {
name: 'CSD - Period 2',
size: 27,
Expand Down
17 changes: 10 additions & 7 deletions apps/src/lib/ui/lti/sync/LtiSectionSyncDialog.tsx
Expand Up @@ -94,13 +94,16 @@ export default function LtiSectionSyncDialog({
'https://support.code.org/hc/en-us/articles/115000488132-Creating-a-Classroom-Section';
const aboutSyncingUrl = LmsLinks.ROSTER_SYNC_INSTRUCTIONS_URL;
const dialogTitle = i18n.ltiSectionSyncDialogTitle();
const dialogDescription = i18n.ltiSectionSyncDialogDescription({
aboutSectionsUrl,
aboutSyncingUrl,
});
const dialogDescription =
syncResult.changed && Object.keys(syncResult.changed).length > 0
? i18n.ltiSectionSyncDialogDescription({
aboutSectionsUrl,
aboutSyncingUrl,
})
: i18n.ltiSectionSyncDialogDescriptionNoChange({aboutSyncingUrl});
let sectionListItems;
if (syncResult && syncResult.all) {
sectionListItems = Object.entries(syncResult.all).map(
if (syncResult && syncResult.changed) {
sectionListItems = Object.entries(syncResult.changed).map(
([section_id, section]) => {
const studentCount = i18n.ltiSectionSyncDialogStudentCount({
numberOfStudents: section.size,
Expand Down Expand Up @@ -187,7 +190,7 @@ const LtiSectionShape = PropTypes.shape({
});
export const LtiSectionSyncResultShape = PropTypes.shape({
all: PropTypes.objectOf(LtiSectionShape),
updated: PropTypes.objectOf(LtiSectionShape),
changed: PropTypes.objectOf(LtiSectionShape),
error: PropTypes.string,
});

Expand Down
2 changes: 1 addition & 1 deletion apps/src/lib/ui/lti/sync/types.ts
Expand Up @@ -7,7 +7,7 @@ export type LtiSectionMap = {[sectionId: string]: LtiSection};

export interface LtiSectionSyncResult {
all?: LtiSectionMap;
updated?: LtiSectionMap;
changed?: LtiSectionMap;
error?: string;
}

Expand Down
4 changes: 2 additions & 2 deletions apps/src/music/player/MusicLibrary.ts
Expand Up @@ -40,7 +40,7 @@ export default class MusicLibrary {
}

if (libraryJson.key) {
this.key = Key[libraryJson.key.toUpperCase() as keyof typeof Key];
this.key = libraryJson.key;
}
}

Expand Down Expand Up @@ -222,7 +222,7 @@ export type LibraryJson = {
imageSrc: string;
path: string;
bpm?: number;
key?: string;
key?: number;
defaultSound?: string;
folders: SoundFolder[];
instruments: SoundFolder[];
Expand Down
6 changes: 3 additions & 3 deletions apps/src/p5lab/spritelab/commands/validationCommands.js
Expand Up @@ -125,17 +125,17 @@ export const commands = {
setBonusSuccessMessage(message) {
this.bonusSuccessMessage = message;
},
setEarlyTime(frames) {
this.validationFrames.early = frames;
},
setWaitTime(frames) {
this.validationFrames.fail = frames;
return true;
},
setFailTime(frames) {
this.validationFrames.fail = frames;
return true;
},
setDelayTime(frames) {
this.validationFrames.delay = frames;
return true;
},
getFailTime() {
return this.validationFrames.fail;
Expand Down
37 changes: 24 additions & 13 deletions apps/src/sites/studio/pages/teacher_dashboard/show.js
Expand Up @@ -56,37 +56,48 @@ $(document).ready(function () {
sectionStandardsProgress,
locales,
});

const selectedSectionFromList = sections.find(s => s.id === section.id);
const selectedSection = {...selectedSectionFromList, ...section};

const store = getStore();
store.dispatch(
setCurrentUserHasSeenStandardsReportInfo(hasSeenStandardsReportInfo)
);
store.dispatch(setSections(sections));
store.dispatch(selectSection(section.id));
store.dispatch(setStudentsForCurrentSection(section.id, section.students));
store.dispatch(setRosterProvider(section.login_type));
store.dispatch(setRosterProviderName(section.login_type_name));
store.dispatch(setLoginType(section.login_type));
store.dispatch(selectSection(selectedSection.id));
store.dispatch(
setStudentsForCurrentSection(selectedSection.id, selectedSection.students)
);
store.dispatch(setRosterProvider(selectedSection.login_type));
store.dispatch(setRosterProviderName(selectedSection.login_type_name));
store.dispatch(setLoginType(selectedSection.login_type));
store.dispatch(setLocaleCode(localeCode));

// DCDO Flag - show/hide Lock Section field
store.dispatch(setShowLockSectionField(scriptData.showLockSectionField));

if (!section.sharing_disabled && section.script.project_sharing) {
if (
!selectedSection.sharing_disabled &&
selectedSection.script.project_sharing
) {
store.dispatch(setShowSharingColumn(true));
}

// Default the scriptId to the script assigned to the section
const defaultScriptId = section.script ? section.script.id : null;
const defaultScriptId = selectedSection.script
? selectedSection.script.id
: null;
if (defaultScriptId) {
store.dispatch(setScriptId(defaultScriptId));
}
// Reorder coursesWithProgress so that the current section is at the top and other sections are in order from newest to oldest
const reorderedCourses = [
...coursesWithProgress.filter(
course => course.id !== section.course_version_id
course => course.id !== selectedSection.course_version_id
),
...coursesWithProgress.filter(
course => course.id === section.course_version_id
course => course.id === selectedSection.course_version_id
),
].reverse();
store.dispatch(setCoursesWithProgress(reorderedCourses));
Expand All @@ -102,14 +113,14 @@ $(document).ready(function () {
<TeacherDashboard
{...props}
studioUrlPrefix={scriptData.studioUrlPrefix}
sectionId={section.id}
sectionName={section.name}
studentCount={section.students.length}
sectionId={selectedSection.id}
sectionName={selectedSection.name}
studentCount={selectedSection.students.length}
coursesWithProgress={coursesWithProgress}
showAITutorTab={showAITutorTab}
sectionProviderName={sectionProviderName(
store.getState(),
section.id
selectedSection.id
)}
/>
)}
Expand Down

0 comments on commit 7e8afbe

Please sign in to comment.