Skip to content

Commit

Permalink
Merge pull request #2 from GuiLeme/h5p-json-acceptance
Browse files Browse the repository at this point in the history
feat: Accept h5p.json and code cleanup
  • Loading branch information
antobinary authored Jul 5, 2024
2 parents 6b7fc3d + 1b920b0 commit 48b3cfd
Show file tree
Hide file tree
Showing 21 changed files with 140 additions and 75 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"@types/react": "^18.2.13",
"@types/react-dom": "^18.2.7",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"bigbluebutton-html-plugin-sdk": "0.0.53",
"bigbluebutton-html-plugin-sdk": "0.0.54",
"h5p-standalone": "file:lib/h5p-standalone",
"path": "^0.12.7",
"react": "^18.2.0",
Expand Down
8 changes: 8 additions & 0 deletions src/commons/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@ export interface CurrentH5pStateWindow extends Window {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
H5P: any;
}

export interface H5pAsJsonObject {
title:string ;
mainLibrary:string ;
language:string ;
preloadedDependencies:string ;
embedTypes:string ;
}
18 changes: 13 additions & 5 deletions src/components/generic-component/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import { useEffect } from 'react';
import * as React from 'react';
import {
GenericContentRenderFunctionProps,
LADTestResult,
TestResult, UserH5pCurrentState, UsersMoreInformationGraphqlResponse,
} from './types';
import NonPresenterViewComponent from './non-presenter-view/component';
import PresenterViewComponent from './presenter-view/component';
import { USERS_MORE_INFORMATION } from './subscriptions';
import { extractH5pContents } from '../h5p-plugin/utils';

export function GenericContentRenderFunction(props: GenericContentRenderFunctionProps) {
const {
jsonContent, currentUser,
h5pContentText, currentUser,
pluginUuid,
} = props;

Expand All @@ -32,7 +34,8 @@ export function GenericContentRenderFunction(props: GenericContentRenderFunction

// TODO: Refactor the test results to be just a request done for an external server to be
// validated and all
const { data: testResult, pushEntry: pushEntryTestResult } = pluginApi.useDataChannel<TestResult>('testResult', DataChannelTypes.LATEST_ITEM);
const { pushEntry: pushEntryTestResult } = pluginApi.useDataChannel<TestResult>('testResult', DataChannelTypes.LATEST_ITEM);
const { pushEntry: pushEntryLadTestResult } = pluginApi.useDataChannel<LADTestResult>('testResult', DataChannelTypes.LATEST_ITEM, 'learning-analytics-dashboard');

useEffect(() => () => {
if (currentUser && currentUser.presenter) deleteUserH5pCurrentStateList([RESET_DATA_CHANNEL]);
Expand All @@ -46,25 +49,30 @@ export function GenericContentRenderFunction(props: GenericContentRenderFunction
(h5pState) => h5pState.payloadJson.userId === currentUser?.userId,
).map((h5pState) => ({ entryId: h5pState.entryId, payloadJson: h5pState.payloadJson }))[0];

const { contentAsJson, h5pAsJson } = extractH5pContents(h5pContentText);

// TODO: Filter the ones where the loading is not done yet (needs refactor in html5)
// if (responseUserH5pCurrentStateList.loading) return null;
return (
currentUserPresenter
? (
<PresenterViewComponent
currentUserId={currentUser?.userId}
testResult={testResult}
usersList={usersList}
h5pLatestStateUpdate={responseUserH5pCurrentStateList}
jsonContent={jsonContent}
contentAsJson={contentAsJson}
h5pAsJson={h5pAsJson}
/>
)
: (
<NonPresenterViewComponent
pluginApi={pluginApi}
currentUserName={currentUser?.name}
currentUserId={currentUser?.userId}
jsonContent={jsonContent}
contentAsJson={contentAsJson}
h5pAsJson={h5pAsJson}
pushEntryTestResult={pushEntryTestResult}
pushEntryLadTestResult={pushEntryLadTestResult}
pushH5pCurrentState={pushUserH5pCurrentStateList}
lastUpdateId={responseObject?.entryId}
lastPayloadJson={responseObject?.payloadJson}
Expand Down
18 changes: 12 additions & 6 deletions src/components/generic-component/h5p-renderer/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export const renderH5p = (
currentH5pStateToBeApplied,
lastPayloadJson,
setH5pState,
jsonContent,
contentAsJson,
h5pAsJson,
setContentRendered,
customCss,
) => async () => {
Expand All @@ -32,7 +33,8 @@ export const renderH5p = (
{
state: JSON.stringify(previousState),
}],
contentAsJson: jsonContent.replace(/(\r\n|\n|\r)/gm, ''),
contentAsJson: contentAsJson.replace(/(\r\n|\n|\r)/gm, ''),
h5pAsJson: h5pAsJson.replace(/(\r\n|\n|\r)/gm, ''),
customCss,
h5pJsonPath: 'https://bigbluebutton.nyc3.digitaloceanspaces.com/plugins/h5p/assets',
frameJs: 'https://bigbluebutton.nyc3.digitaloceanspaces.com/plugins/h5p/assets/frame.bundle.js',
Expand All @@ -52,22 +54,25 @@ export const renderH5pForNonPresenter = (
containerRef,
lastPayloadJson,
setH5pState,
jsonContent,
contentAsJson,
h5pAsJson,
setContentRendered,
) => renderH5p(
containerRef,
false,
undefined,
lastPayloadJson,
setH5pState,
jsonContent,
contentAsJson,
h5pAsJson,
setContentRendered,
);

export const renderH5pForPresenter = (
containerRef,
currentH5pStateToBeApplied,
jsonContent,
contentAsJson,
h5pAsJson,
setContentRendered,
customCss,
) => renderH5p(
Expand All @@ -76,7 +81,8 @@ export const renderH5pForPresenter = (
currentH5pStateToBeApplied,
'',
() => {},
jsonContent,
contentAsJson,
h5pAsJson,
setContentRendered,
customCss,
);
25 changes: 18 additions & 7 deletions src/components/generic-component/non-presenter-view/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from 'react';
import { renderH5pForNonPresenter } from '../h5p-renderer/utils';
import { NonPresenterViewComponentProps } from './types';
import * as Styled from '../styles';
import { CurrentH5pStateWindow } from '../../../commons/types';
import { CurrentH5pStateWindow, H5pAsJsonObject } from '../../../commons/types';

declare const window: CurrentH5pStateWindow;

Expand All @@ -15,20 +15,29 @@ function NonPresenterViewComponent(props: NonPresenterViewComponentProps) {
const [contentRendered, setContentRendered] = useState(false);
const [h5pState, setH5pState] = useState({});
const {
jsonContent, currentUserName,
pushEntryTestResult, currentUserId,
contentAsJson, currentUserName, h5pAsJson,
pushEntryTestResult, pushEntryLadTestResult, currentUserId,
pushH5pCurrentState, lastUpdateId, lastPayloadJson,
replaceH5pCurrentState,
replaceH5pCurrentState, pluginApi,
} = props;

const h5pAsJsonObject: H5pAsJsonObject = JSON.parse(h5pAsJson);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const eventHandler = (event: any) => {
if (event.getScore && event.getMaxScore && event.getVerb && pushEntryTestResult) {
if (event.getScore && event.getMaxScore && event.getVerb
&& pushEntryTestResult && pushEntryLadTestResult) {
const score = event.getScore();
const maxScore = event.getMaxScore();
const verb = event.getVerb();
if (verb === 'answered') {
pluginApi.sendGenericDataForLearningAnalyticsDashboard({
columnTitle: h5pAsJsonObject.title,
value: `${(parseFloat(score) / parseFloat(maxScore)) * 10.0} / 10`,
cardTitle: 'H5P',
});
pushEntryTestResult({
testResultActivityTitle: h5pAsJsonObject.title,
userId: currentUserId,
testResultObject: score,
testResultMaximumScore: maxScore,
Expand Down Expand Up @@ -64,7 +73,8 @@ function NonPresenterViewComponent(props: NonPresenterViewComponentProps) {
containerRef,
lastPayloadJson,
setH5pState,
jsonContent,
contentAsJson,
h5pAsJson,
setContentRendered,
),
100,
Expand All @@ -75,7 +85,8 @@ function NonPresenterViewComponent(props: NonPresenterViewComponentProps) {
clearTimeout(timeoutReference);
};
}, []);
if (pushEntryTestResult && !stopInfinitLoop.current && contentRendered) {
if (pushEntryTestResult
&& pushEntryLadTestResult && !stopInfinitLoop.current && contentRendered) {
stopInfinitLoop.current = true;
window.H5P?.externalDispatcher?.on('xAPI', eventHandler);
}
Expand Down
9 changes: 6 additions & 3 deletions src/components/generic-component/non-presenter-view/types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { ReplaceEntryFunction } from 'bigbluebutton-html-plugin-sdk/dist/cjs/data-channel/types';
import { PushEntryFunction } from 'bigbluebutton-html-plugin-sdk';
import { TestResult, UserH5pCurrentState } from '../types';
import { PluginApi, PushEntryFunction } from 'bigbluebutton-html-plugin-sdk';
import { LADTestResult, TestResult, UserH5pCurrentState } from '../types';

export interface NonPresenterViewComponentProps {
currentUserName: string;
jsonContent: string;
contentAsJson: string;
h5pAsJson: string;
pushEntryTestResult: PushEntryFunction<TestResult>;
pushEntryLadTestResult: PushEntryFunction<LADTestResult>;
currentUserId: string;
pushH5pCurrentState: PushEntryFunction<UserH5pCurrentState>;
lastUpdateId: string;
pluginApi: PluginApi;
lastPayloadJson: UserH5pCurrentState;
replaceH5pCurrentState: ReplaceEntryFunction<UserH5pCurrentState>;
}
16 changes: 8 additions & 8 deletions src/components/generic-component/presenter-view/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,28 @@ import { H5pPlayerManagerComponent } from './h5p-player-manager/component';

const mapObject = (
currentUserH5pStateList: DataChannelEntryResponseType<UserH5pCurrentState>[],
jsonContent: string,
contentAsJson: string,
h5pAsJson: string,
) => (
currentUserH5pStateList?.map((item) => (
<H5pPlayerManagerComponent
key={item.payloadJson.userId}
userId={item.payloadJson.userId}
userName={item.payloadJson.userName}
contentAsJson={contentAsJson}
currentH5pStateToBeApplied={(item.payloadJson.currentState)
? JSON.parse(item.payloadJson.currentState) : {}}
jsonContent={jsonContent}
h5pAsJson={h5pAsJson}
/>
))
);

function PresenterViewComponent(props: PresenterViewComponentProps) {
const {
h5pLatestStateUpdate, jsonContent, testResult,
h5pLatestStateUpdate, contentAsJson, h5pAsJson,
} = props;

const userIdTestResultList = testResult?.data?.map((item) => item.payloadJson.userId);
const dataToBeRendered = h5pLatestStateUpdate?.data?.filter(
(item) => !userIdTestResultList?.includes(item?.payloadJson.userId),
);
const dataToBeRendered = h5pLatestStateUpdate?.data;

return (
<div
Expand All @@ -45,7 +45,7 @@ function PresenterViewComponent(props: PresenterViewComponentProps) {
}
>
<Styled.H5pWrapper>
{mapObject(dataToBeRendered, jsonContent)}
{mapObject(dataToBeRendered, contentAsJson, h5pAsJson)}
</Styled.H5pWrapper>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import H5pPresenterComponent from '../h5p-presenter-component/component';

export function H5pPlayerManagerComponent(props: H5pPlayerManagerComponentProps) {
const {
jsonContent,
contentAsJson, h5pAsJson,
userName,
currentH5pStateToBeApplied,
} = props;
Expand Down Expand Up @@ -41,7 +41,8 @@ export function H5pPlayerManagerComponent(props: H5pPlayerManagerComponentProps)
setLatestH5pStates={setLatestH5pStates}
currentH5pStateToBeApplied={state.state}
idOfCurrentState={state.id}
jsonContent={jsonContent}
contentAsJson={contentAsJson}
h5pAsJson={h5pAsJson}
/>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export interface H5pPlayerManagerComponentProps {
currentH5pStateToBeApplied: object;
userName: string
jsonContent: string;
contentAsJson: string;
h5pAsJson: string;
currentH5pStateToBeApplied: object;
userId: string;
}

export interface LatestH5pStateItem {
id: string;
state: object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { renderH5pForPresenter } from '../../h5p-renderer/utils';
import * as Styled from '../../styles';
import { H5pPresenterComponentProps } from './types';
import { CurrentH5pStateWindow } from '../../../../commons/types';
import './custom-crossword.css';

declare const window: CurrentH5pStateWindow;

Expand All @@ -14,7 +13,7 @@ function H5pPresenterComponent(props: H5pPresenterComponentProps) {
const [contentRendered, setContentRendered] = useState(false);

const {
jsonContent,
contentAsJson, h5pAsJson,
currentH5pStateToBeApplied,
setLatestH5pStates, idOfCurrentState,
} = props;
Expand All @@ -39,7 +38,8 @@ function H5pPresenterComponent(props: H5pPresenterComponentProps) {
renderH5pForPresenter(
containerRef,
currentH5pStateToBeApplied,
jsonContent,
contentAsJson,
h5pAsJson,
setContentRendered,
['https://bigbluebutton.nyc3.digitaloceanspaces.com/plugins/h5p/assets/custom/css/custom-crossword.css'],
),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { LatestH5pStateItem } from '../h5p-player-manager/types';

export interface H5pPresenterComponentProps {
jsonContent: string;
contentAsJson: string;
h5pAsJson: string;
indexOfCurrentStateInList: number;
stateListLength: number;
currentH5pStateToBeApplied: object;
Expand Down
Loading

0 comments on commit 48b3cfd

Please sign in to comment.