Skip to content

Commit

Permalink
feat(3.3.0): project reset with progress (#507)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaunSHamilton authored Mar 5, 2024
2 parents 916a555 + c729602 commit b72ee78
Show file tree
Hide file tree
Showing 24 changed files with 337 additions and 90 deletions.
34 changes: 30 additions & 4 deletions .freeCodeCamp/client/components/controls.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
import { useEffect, useState } from 'react';
import { F, ProjectI, TestType } from '../types';
import { F, LoaderT, ProjectI, TestType } from '../types';

interface ControlsProps {
cancelTests: F<void, void>;
runTests: F<void, void>;
resetProject?: F<void, void>;
isResetEnabled?: ProjectI['isResetEnabled'];
tests: TestType[];
loader?: LoaderT;
}

// Changes the Reset button background to a filling progress bar when the seed is running
function progressStyle(loader?: LoaderT) {
if (!loader) {
return {};
}

const {
isLoading,
progress: { total, count }
} = loader;
if (isLoading) {
return {
background: `linear-gradient(to right, #0065A9 ${
(count / total) * 100
}%, rgba(0,0,0,0) 0%)`
};
}
}

export const Controls = ({
cancelTests,
runTests,
resetProject,
isResetEnabled,
tests
tests,
loader
}: ControlsProps) => {
const [isTestsRunning, setIsTestsRunning] = useState(false);

Expand All @@ -34,15 +55,20 @@ export const Controls = ({
}
}

const resetDisabled = !isResetEnabled || loader?.isLoading;

return (
<section className='project-controls'>
<button className='secondary-cta' onClick={handleTests}>
{isTestsRunning ? 'Cancel Tests' : 'Run Tests'}
</button>
{resetProject && (
<button
disabled={!isResetEnabled}
style={isResetEnabled ? {} : { cursor: 'not-allowed' }}
disabled={resetDisabled}
style={{
...progressStyle(loader),
cursor: resetDisabled ? 'not-allowed' : 'pointer'
}}
onClick={() => resetProject()}
>
Reset Step
Expand Down
37 changes: 16 additions & 21 deletions .freeCodeCamp/client/components/output.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { useState } from 'react';
import { Loader } from './loader';
import { ConsoleError, TestType } from '../types';
import { Tests } from './tests';
import { Console } from './console';
import { Hints } from './hints';

interface OutputProps {
isLoading: boolean;
hints: string[];
tests: TestType[];
cons: ConsoleError[];
}

export const Output = ({ isLoading, hints, tests, cons }: OutputProps) => {
export const Output = ({ hints, tests, cons }: OutputProps) => {
const [selectedBtn, setSelectedBtn] = useState('tests');

return (
Expand Down Expand Up @@ -54,24 +52,21 @@ export const Output = ({ isLoading, hints, tests, cons }: OutputProps) => {
</li>
) : null}
</ul>
{isLoading ? (
<Loader />
) : (
<div className='project-output-content'>
{(() => {
switch (selectedBtn) {
case 'tests':
return <Tests tests={tests} />;
case 'console':
return <Console cons={cons} />;
case 'hints':
return <Hints hints={hints} />;
default:
return <div>No content</div>;
}
})()}
</div>
)}

<div className='project-output-content'>
{(() => {
switch (selectedBtn) {
case 'tests':
return <Tests tests={tests} />;
case 'console':
return <Console cons={cons} />;
case 'hints':
return <Hints hints={hints} />;
default:
return <div>No content</div>;
}
})()}
</div>
</section>
);
};
20 changes: 20 additions & 0 deletions .freeCodeCamp/client/components/progress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';

type ProgressProps = {
total: number;
count: number;
};

export function Progress({ total, count }: ProgressProps) {
const [value, setValue] = useState(0.0);

useEffect(() => {
setValue(count / total);
}, [count]);

return (
<label>
Resetting: <progress value={value}></progress>
</label>
);
}
18 changes: 13 additions & 5 deletions .freeCodeCamp/client/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ConsoleError,
Events,
FreeCodeCampConfigI,
LoaderT,
ProjectI,
TestType
} from './types/index';
Expand Down Expand Up @@ -34,7 +35,10 @@ const App = () => {
const [tests, setTests] = useState<TestType[]>([]);
const [hints, setHints] = useState<string[]>([]);
const [cons, setCons] = useState<ConsoleError[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [loader, setLoader] = useState({
isLoading: false,
progress: { count: 0, total: 1 }
});
const [alertCamper, setAlertCamper] = useState<null | string>(null);
const [error, setError] = useState<Error | null>(null);

Expand Down Expand Up @@ -77,7 +81,7 @@ const App = () => {

const handle = {
'handle-project-finish': handleProjectFinish,
'toggle-loader-animation': toggleLoaderAnimation,
'update-loader': updateLoader,
'update-test': updateTest,
'update-tests': updateTests,
'update-hints': updateHints,
Expand Down Expand Up @@ -161,6 +165,10 @@ const App = () => {
setError(error);
}

function updateLoader({ loader }: { loader: LoaderT }) {
setLoader(loader);
}

function resetTests() {
setTests([]);
}
Expand All @@ -171,8 +179,8 @@ const App = () => {
setCons([]);
}

function toggleLoaderAnimation() {
setIsLoading(prev => !prev);
function toggleLoaderAnimation({ loader }: { loader: LoaderT }) {
setLoader(loader);
}

function runTests() {
Expand Down Expand Up @@ -215,7 +223,7 @@ const App = () => {
goToNextLesson,
goToPreviousLesson,
hints,
isLoading,
loader,
lessonNumber,
project,
resetProject,
Expand Down
28 changes: 18 additions & 10 deletions .freeCodeCamp/client/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,26 @@ p {
/* get rid of bad outlines */
background: conic-gradient(#0000, var(--c)) content-box;
-webkit-mask:
/* we use +/-1deg between colors to avoid jagged edges */
repeating-conic-gradient(#0000 0deg,
/* we use +/-1deg between colors to avoid jagged edges */ repeating-conic-gradient(
#0000 0deg,
#000 1deg calc(360deg / var(--n) - var(--g) - 1deg),
#0000 calc(360deg / var(--n) - var(--g)) calc(360deg / var(--n))),
radial-gradient(farthest-side,
#0000 calc(360deg / var(--n) - var(--g)) calc(360deg / var(--n))
),
radial-gradient(
farthest-side,
#0000 calc(98% - var(--b)),
#000 calc(100% - var(--b)));
mask: repeating-conic-gradient(#0000 0deg,
#000 calc(100% - var(--b))
);
mask: repeating-conic-gradient(
#0000 0deg,
#000 1deg calc(360deg / var(--n) - var(--g) - 1deg),
#0000 calc(360deg / var(--n) - var(--g)) calc(360deg / var(--n))),
radial-gradient(farthest-side,
#0000 calc(360deg / var(--n) - var(--g)) calc(360deg / var(--n))
),
radial-gradient(
farthest-side,
#0000 calc(98% - var(--b)),
#000 calc(100% - var(--b)));
#000 calc(100% - var(--b))
);
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--n));
Expand Down Expand Up @@ -146,6 +153,7 @@ p {
transform: rotate(1turn);
}
}

.hidden {
display: none;
}
Expand Down Expand Up @@ -245,4 +253,4 @@ details {
color: var(--light-2);
background-color: var(--dark-3);
cursor: pointer;
}
}
11 changes: 6 additions & 5 deletions .freeCodeCamp/client/templates/project.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Description } from '../components/description';
import { Heading } from '../components/heading';
import { ConsoleError, F, ProjectI, TestType } from '../types';
import { ConsoleError, F, LoaderT, ProjectI, TestType } from '../types';
import { Controls } from '../components/controls';
import { Output } from '../components/output';
import './project.css';
Expand All @@ -14,7 +14,7 @@ export interface ProjectProps {
cons: ConsoleError[];
description: string;
hints: string[];
isLoading: boolean;
loader: LoaderT;
lessonNumber: number;
project: ProjectI;
tests: TestType[];
Expand All @@ -26,7 +26,7 @@ export const Project = ({
resetProject,
goToNextLesson,
goToPreviousLesson,
isLoading,
loader,
project,
lessonNumber,
description,
Expand Down Expand Up @@ -63,11 +63,12 @@ export const Project = ({
runTests,
resetProject,
isResetEnabled: project.isResetEnabled,
tests
tests,
loader
})}
/>

<Output {...{ isLoading, hints, tests, cons }} />
<Output {...{ hints, tests, cons }} />
</div>
</>
);
Expand Down
8 changes: 8 additions & 0 deletions .freeCodeCamp/client/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export type TestType = {
testId: number;
};

export type LoaderT = {
isLoading: boolean;
progress: {
total: number;
count: number;
};
};

export interface ProjectI {
id: number;
title: string;
Expand Down
5 changes: 5 additions & 0 deletions .freeCodeCamp/plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export const pluginEvents = {
*/
onLessonFailed: async project => {},

/**
* @param {Project} project
*/
onLessonLoad: async project => {},

/**
* @param {string} projectDashedName
* @returns {Promise<{title: string; description: string; numberOfLessons: number; tags: string[]}>}
Expand Down
4 changes: 2 additions & 2 deletions .freeCodeCamp/tooling/client-socks.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { parseMarkdown } from './parser.js';

export function toggleLoaderAnimation(ws) {
ws.send(parse({ event: 'toggle-loader-animation' }));
export function updateLoader(ws, loader) {
ws.send(parse({ event: 'update-loader', data: { loader } }));
}

/**
Expand Down
5 changes: 5 additions & 0 deletions .freeCodeCamp/tooling/hot-reload.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export function hotReload(ws, pathsToIgnore = defaultPathsToIgnore) {
let testsRunning = false;
let isClearConsole = false;

// hotReload is called on connection, which can happen mulitple times due to client reload/disconnect.
// This ensures the following does not happen:
// > MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 all listeners added to [FSWatcher].
watcher.removeAllListeners('all');

watcher.on('all', async (event, name) => {
if (name && !pathsToIgnore.find(p => name.includes(p))) {
if (isWait) return;
Expand Down
1 change: 1 addition & 0 deletions .freeCodeCamp/tooling/lesson.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export async function runLesson(ws, projectDashedName) {
if (currentLesson === 0) {
await pluginEvents.onProjectStart(project);
}
await pluginEvents.onLessonLoad(project);

updateProject(ws, project);

Expand Down
Loading

0 comments on commit b72ee78

Please sign in to comment.