Skip to content

Commit

Permalink
Merge branch 'Simon-Initiative:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
dtiwarATS authored Dec 13, 2024
2 parents d97c589 + eee562f commit af98bf8
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 29 deletions.
15 changes: 15 additions & 0 deletions assets/src/adaptivity/scripting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,21 @@ export const getAssignStatements = (
return letStatements;
};

export const setVariableWithTypeAssignStatements = (
state: Record<string, any>,
partId: string,
): void => {
const variableWithTypeAssignStatements = Object.keys(state).reduce((collect: any, key) => {
const value = state[key];
collect[key] = { type: value?.type || 0, allowedValues: value?.allowedValues || null };
return collect;
}, {});
const myQuery = `let {stage.${partId}.variables.Type} = ${JSON.stringify(
variableWithTypeAssignStatements,
)};`;
evalScript(myQuery, defaultGlobalEnv);
};

export const getAssignScript = (
state: Record<string, any>,
env: Environment = defaultGlobalEnv,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ import { selectProjectSlug } from '../../../store/app/slice';
import { MediaPickerModal } from '../../Modal/MediaPickerModal';
import { MediaBrowserComponent, TorusMediaBrowserWrapper } from './TorusMediaBrowserWrapper';

const _TorusImageBrowser: MediaBrowserComponent = ({ id, label, value, onChange, onBlur }) => {
const _TorusImageBrowser: MediaBrowserComponent = ({
id,
label,
value,
onChange,
onBlur,
onFocus,
}) => {
const [pickerOpen, , openPicker, closePicker] = useToggle();
const projectSlug: string = useSelector(selectProjectSlug);

Expand All @@ -33,7 +40,10 @@ const _TorusImageBrowser: MediaBrowserComponent = ({ id, label, value, onChange,
{hasImage || <div className="truncate-left">No Image</div>}

<Button
onClick={openPicker}
onClick={() => {
if (onFocus) onFocus();
openPicker();
}}
type="button"
variant="secondary"
size="sm"
Expand All @@ -42,7 +52,14 @@ const _TorusImageBrowser: MediaBrowserComponent = ({ id, label, value, onChange,
<i className="fa-solid fa-image"></i>
</Button>

<a href="#" style={{ marginLeft: '5px', textDecoration: 'underline' }} onClick={openPicker}>
<a
href="#"
style={{ marginLeft: '5px', textDecoration: 'underline' }}
onClick={() => {
if (onFocus) onFocus();
openPicker();
}}
>
Upload or Link Image
</a>
{pickerOpen && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface MediaBrowserProps {
value: string;
onChange: (url: string) => void;
onBlur: (id: string, url: string) => void;
onFocus?: () => void;
}

export type MediaBrowserComponent = React.FC<MediaBrowserProps>;
Expand All @@ -43,6 +44,9 @@ export const TorusMediaBrowserWrapper = (
value={props.value}
onChange={(event) => props.onChange(event.target.value)}
onBlur={(event) => props.onBlur(props.id, event.target.value)}
onFocus={() => {
if (props.onFocus) props.onFocus();
}}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,9 @@ export const PartPropertyEditor: React.FC<Props> = ({
const selectPartType = selectedPartDef?.type || '';

return (
<div className={`component-tab p-3 overflow-hidden part-property-editor ${selectPartType}`}>
<div
className={`component-tab p-3 overflow-hidden part-property-editor ${selectPartType}-part-property`}
>
{selectedPartDef && partEditMode === 'expert' && (
<ButtonToolbar aria-label="Component Tools">
<ButtonGroup className="me-2" aria-label="First group">
Expand Down
33 changes: 32 additions & 1 deletion assets/src/apps/delivery/components/preview-tools/Inspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,43 @@ const Inspector: React.FC<InspectorProps> = () => {
return setStageState(stageSlice);
};

const getVariablesTypeState = (allState: any) => {
const variableTypes: Array<any> = [];
Object.keys(allState).map((key) => {
if (key.includes('.variables.Type')) {
Object.keys(allState[key]).map((childKey) => {
const variableState = allState[key];
//the key will look like 'stage.partId.variables.Type'. We need an array with 'stage.partId.capivariable' so we split the key and get the first section
const arrVariableKey = key.split('.variables.Type');
if (arrVariableKey?.length > 1) {
const parent = key.split('.variables.Type')[0];
variableTypes.push({
key: `${parent}.${childKey}`,
type: variableState[childKey].type,
allowedValues: variableState[childKey].allowedValues,
});
}
}, {});
}
}, {});
return variableTypes;
};
// change handler fires for every key, and there are often several at once
const debounceStateChanges = useCallback(
debounce(() => {
const allState = getEnvState(defaultGlobalEnv);
const variableTypes: Array<any> = getVariablesTypeState(allState);
const globalStateAsVars = Object.keys(allState).reduce((collect: any, key) => {
collect[key] = new CapiVariable({ key, value: allState[key] });
const result = variableTypes?.filter((part) => key.includes(part.key));
const variableType = result?.length ? result[0].type : 0;
//We need this because when the variable type is ENUM, we get the allowed values that gets displayed in dropdown
const variableAllowedValues = result?.length ? result[0]?.allowedValues || null : null;
collect[key] = new CapiVariable({
key,
value: allState[key],
type: variableType,
allowedValues: variableAllowedValues,
});
return collect;
}, {});
setGlobalState(globalStateAsVars);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const RestartLessonDialog: React.FC<RestartLessonDialogProps> = ({ onRestart })
}}
>
<div className="modal-header">
<h3>Restart Lesson</h3>
<h3>{graded ? 'Submit Attempt' : 'Restart Lesson'}</h3>
<button
type="button"
className="close"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { navigateToActivity } from '../../../store/features/groups/actions/deck'
import { selectSequence } from '../../../store/features/groups/selectors/deck';
import {
selectEnableHistory,
selectIsGraded,
selectShowHistory,
setShowHistory,
} from '../../../store/features/page/slice';
Expand All @@ -30,7 +31,7 @@ const HistoryNavigation: React.FC = () => {
const enableHistory = useSelector(selectEnableHistory);
const showHistory = useSelector(selectShowHistory);
const isHistoryMode = useSelector(selectHistoryNavigationActivity);

const graded = useSelector(selectIsGraded);
const sequences = useSelector(selectSequence);
const dispatch = useDispatch();

Expand Down Expand Up @@ -168,7 +169,9 @@ const HistoryNavigation: React.FC = () => {
<button onClick={restartHandler} className="theme-no-history-restart">
<span>
<div className="theme-no-history-restart__icon" />
<span className="theme-no-history-restart__label">Restart Lesson</span>
<span className="theme-no-history-restart__label">
{graded ? 'Submit Attempt' : 'Restart Lesson'}
</span>
</span>
</button>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { setRestartLesson } from 'apps/delivery/store/features/adaptivity/slice';
import {
selectEnableHistory,
selectIsGraded,
selectPreviewMode,
selectShowHistory,
setShowHistory,
Expand All @@ -14,6 +15,7 @@ export interface OptionsPanelProps {

const OptionsPanel: React.FC<OptionsPanelProps> = ({ open }) => {
const dispatch = useDispatch();
const graded = useSelector(selectIsGraded);
const enableHistory = useSelector(selectEnableHistory);
const showHistory = useSelector(selectShowHistory);
const isPreviewMode = useSelector(selectPreviewMode);
Expand Down Expand Up @@ -65,7 +67,7 @@ const OptionsPanel: React.FC<OptionsPanelProps> = ({ open }) => {
aria-label="Open restart lesson window"
onClick={handleRestartLesson}
>
Restart Lesson
{graded ? 'Submit Attempt' : 'Restart Lesson'}
</button>
</div>
<div className="option logoutOption displayNone">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
evalScript,
getAssignStatements,
getValue,
setVariableWithTypeAssignStatements,
} from '../../../../../../adaptivity/scripting';
import { deferredSavePart } from '../../../../../../data/persistence/deferredSavePart';
import { DeliveryRootState } from '../../../rootReducer';
Expand Down Expand Up @@ -40,7 +41,11 @@ export const savePartState = createAsyncThunk(
if (p.attemptGuid === partAttemptRecord.attemptGuid) {
// always want to merge the previous response inputs into the attempt
// overwrite with later info, but don't delete
updatedPartResponses = { ...result.response, ...updatedPartResponses };
updatedPartResponses = {
...result.response,
...updatedPartResponses,
partId: p.partId,
};
result.response = updatedPartResponses;
}
return result;
Expand All @@ -49,7 +54,9 @@ export const savePartState = createAsyncThunk(
await dispatch(upsertActivityAttemptState({ attempt: updated }));
}
}

if (isPreviewMode && updatedPartResponses?.partId?.length) {
setVariableWithTypeAssignStatements(updatedPartResponses, updatedPartResponses?.partId);
}
// update scripting env with latest values
const assignScripts = getAssignStatements(updatedPartResponses);
const scriptResult: string[] = [];
Expand Down
10 changes: 6 additions & 4 deletions assets/src/components/activities/adaptive/AdaptiveAuthoring.scss
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
.advanced-authoring {
.part-property-editor.janus-popup .aa-properties-editor .color-picker-widget {
.part-property-editor.janus-popup-part-property .aa-properties-editor .color-picker-widget {
top: 1133px !important;
padding-left: 14px;
}
.part-property-editor.janus-navigation-button .aa-properties-editor .color-picker-widget {
.part-property-editor.janus-navigation-button-part-property
.aa-properties-editor
.color-picker-widget {
top: 559px !important;
padding-left: 14px;
}
.part-property-editor.janus-text-flow .aa-properties-editor .color-picker-widget {
.part-property-editor.janus-text-flow-part-property .aa-properties-editor .color-picker-widget {
top: 506px !important;
padding-left: 14px;
}
//Simple Authoring
.part-property-editor.janus-popup .color-picker-widget {
.part-property-editor.janus-popup-part-property .color-picker-widget {
top: 583px !important;
padding-left: 14px;
}
Expand Down
24 changes: 15 additions & 9 deletions assets/src/components/parts/janus-Carousel/CarouselAuthor.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import React, { CSSProperties, useEffect } from 'react';
import { A11y, Keyboard, Navigation, Pagination, Zoom } from 'swiper';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import 'swiper/css/scrollbar';
import 'swiper/css/zoom';
import { Swiper, SwiperSlide } from 'swiper/react';
import { AuthorPartComponentProps } from 'components/parts/types/parts';
import './Carousel.css';
import { CarouselModel } from './schema';

const CarouselAuthor: React.FC<AuthorPartComponentProps<CarouselModel>> = (props) => {
const { model } = props;

const { z = 0, width, height, fontSize = 16, images } = model;
const { z = 0, width, height, fontSize = 16, images, zoom: carouselZoom } = model;
const styles: CSSProperties = {
fontSize: `${fontSize}px`,
zIndex: z,
overflow: 'hidden',
display: 'flex',
};

const MAGIC_NUMBER = 75;
const imgStyles: CSSProperties = {
maxWidth: `calc(${width}px - ${64}px)`,
maxHeight: `calc(${height}px - ${32}px)`,
maxWidth: `calc(${width}px - ${MAGIC_NUMBER}px)`,
maxHeight: `calc(${height} - ${MAGIC_NUMBER}px)`,
};

useEffect(() => {
Expand All @@ -31,13 +37,13 @@ const CarouselAuthor: React.FC<AuthorPartComponentProps<CarouselModel>> = (props
<div data-janus-type={tagName} className={`janus-image-carousel`} style={styles}>
{images.length > 0 && (
<Swiper
loop
navigation
modules={[Navigation, Pagination, A11y, Keyboard, Zoom]}
slidesPerView={1}
zoom={{ maxRatio: 3 }}
loop={true}
navigation={true}
zoom={carouselZoom ? { maxRatio: 3 } : false}
keyboard={{ enabled: true }}
pagination={{ clickable: true }}
enabled={false}
>
{images.map((image: any, index: number) => (
<SwiperSlide key={index} zoom={true}>
Expand Down
14 changes: 12 additions & 2 deletions assets/src/components/parts/janus-Carousel/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const schema: JSONSchema7Object = {
properties: {
url: {
type: 'string',
description: 'Image URL',
description: '',
},
caption: {
type: 'string',
Expand All @@ -48,7 +48,15 @@ export const schema: JSONSchema7Object = {
},
};

export const uiSchema = {};
export const uiSchema = {
images: {
items: {
url: {
'ui:widget': 'TorusImageBrowser',
},
},
},
};

export const adaptivitySchema = {
'Current Image': CapiVariableTypes.NUMBER,
Expand All @@ -60,4 +68,6 @@ export const createSchema = (): Partial<CarouselModel> => ({
customCssClass: '',
zoom: true,
images: [{ url: '/images/placeholder-image.svg', caption: 'an image at night', alt: 'an image' }],
width: 400,
height: 400,
});
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,9 @@ const ExternalActivity: React.FC<PartComponentProps<CapiIframeModel>> = (props)
key: stateValueKey,
type: msgData.values[stateValueKey] ? msgData.values[stateValueKey].type : null,
value: msgData.values[stateValueKey] ? msgData.values[stateValueKey].value : null,
allowedValues: msgData.values[stateValueKey]
? msgData.values[stateValueKey].allowedValues
: null,
};
return variableObj;
}, {} as any);
Expand Down
6 changes: 3 additions & 3 deletions assets/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14132,9 +14132,9 @@ nano-css@^5.3.1:
stylis "^4.0.6"

nanoid@^3.1.23, nanoid@^3.3.1, nanoid@^3.3.4:
version "3.3.4"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
version "3.3.8"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==

nanomatch@^1.2.9:
version "1.2.13"
Expand Down

0 comments on commit af98bf8

Please sign in to comment.