Skip to content

Commit

Permalink
Add "Hide Done" Option for Tutorials (#10248)
Browse files Browse the repository at this point in the history
This adds a "hideDone" flag that can be set on a tutorial to indicate that the Done button should not be shown on the final step.

Also added tests for hideDone and hideToolbox (which I added in 9e6dd9e). Not sure how much value they bring beyond parsing validation, but I suppose that's better than nothing!
  • Loading branch information
thsparks authored Oct 31, 2024
1 parent 995ee2c commit e3e9ec7
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 8 deletions.
8 changes: 8 additions & 0 deletions docs/writing-docs/tutorials/control-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ For text-based tutorials, you can choose to hide the toolbox altogether. This is
### @hideToolbox true
```

### Hide Done

If you do not wish for your tutorial's final step to display a "Done" button, which sends the user back to the main editor, you can hide it by specifying **@hideDone** in the metadata. The default is ``false``.

```
### @hideDone true
```

## Special blocks

### Templates
Expand Down
1 change: 1 addition & 0 deletions localtypings/pxtarget.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,7 @@ declare namespace pxt.tutorial {
codeStop?: string; // command to run when code stops (MINECRAFT HOC ONLY)
autoexpandOff?: boolean; // INTERNAL TESTING ONLY
preferredEditor?: string; // preferred editor for opening the tutorial
hideDone?: boolean; // Do not show a "Done" button at the end of the tutorial
}

interface TutorialBlockConfigEntry {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"test:err": "gulp testerr",
"test:fmt": "gulp testfmt",
"test:lang": "gulp testlang",
"test:tutorials": "gulp testtutorials",
"update": "gulp update",
"watch-streamer": "cd docs/static/streamer && tsc -t es6 --watch",
"prepare": "node ./scripts/npm-prepare.js",
Expand Down
23 changes: 23 additions & 0 deletions tests/tutorial-test/baselines/hideDone.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"editor": "blocksprj",
"title": "Hide Done",
"steps": [
{
"contentMd": "Tutorials can choose to hide the done button on the final step. This metadata is parsed and removed.",
"headerContentMd": "Tutorials can choose to hide the done button on the final step. This metadata is parsed and removed."
},
{
"contentMd": "Tutorial parsing for hints, steps, etc should function exactly as before.\n\n```blocks\nlet x = 8;\nlet y = x + 2;\n```",
"headerContentMd": "Tutorial parsing for hints, steps, etc should function exactly as before.",
"hintContentMd": "```blocks\nlet x = 8;\nlet y = x + 2;\n```"
}
],
"activities": null,
"code": [
"{\nlet x = 8;\nlet y = x + 2;\n}",
"{\nbasic.showIcon(IconNames.Square)\n}"
],
"metadata": {
"hideDone": true
}
}
23 changes: 23 additions & 0 deletions tests/tutorial-test/baselines/hideToolbox.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"editor": "blocksprj",
"title": "Hide Toolbox",
"steps": [
{
"contentMd": "Tutorials can choose to hide the toolbox. This metadata is parsed and removed.",
"headerContentMd": "Tutorials can choose to hide the toolbox. This metadata is parsed and removed."
},
{
"contentMd": "Tutorial parsing for hints, steps, etc should function exactly as before.\n\n```blocks\nlet x = 8;\nlet y = x + 2;\n```",
"headerContentMd": "Tutorial parsing for hints, steps, etc should function exactly as before.",
"hintContentMd": "```blocks\nlet x = 8;\nlet y = x + 2;\n```"
}
],
"activities": null,
"code": [
"{\nlet x = 8;\nlet y = x + 2;\n}",
"{\nbasic.showIcon(IconNames.Square)\n}"
],
"metadata": {
"hideToolbox": true
}
}
20 changes: 20 additions & 0 deletions tests/tutorial-test/cases/hideDone.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Hide Done

### @hideDone true

## Introduction

Tutorials can choose to hide the done button on the final step. This metadata is parsed and removed.

## Step with hint

Tutorial parsing for hints, steps, etc should function exactly as before.

```blocks
let x = 8;
let y = x + 2;
```

```ghost
basic.showIcon(IconNames.Square)
```
20 changes: 20 additions & 0 deletions tests/tutorial-test/cases/hideToolbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Hide Toolbox

### @hideToolbox true

## Introduction

Tutorials can choose to hide the toolbox. This metadata is parsed and removed.

## Step with hint

Tutorial parsing for hints, steps, etc should function exactly as before.

```blocks
let x = 8;
let y = x + 2;
```

```ghost
basic.showIcon(IconNames.Square)
```
10 changes: 6 additions & 4 deletions webapp/src/components/tutorial/TutorialContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function TutorialContainer(props: TutorialContainerProps) {

const showBack = currentStep !== 0;
const showNext = currentStep !== steps.length - 1;
const showDone = !showNext && !pxt.appTarget.appTheme.lockedEditor && !hideIteration;
const isDone = !showNext && !pxt.appTarget.appTheme.lockedEditor && !hideIteration;
const showImmersiveReader = pxt.appTarget.appTheme.immersiveReader;
const isHorizontal = props.tutorialSimSidebar || pxt.BrowserUtils.isTabletSize();

Expand Down Expand Up @@ -235,10 +235,11 @@ export function TutorialContainer(props: TutorialContainerProps) {
})
}

const hideDone = tutorialOptions.metadata?.hideDone;
const doneButtonLabel = lf("Finish the tutorial.");
const nextButtonLabel = lf("Go to the next step of the tutorial.");
const nextButton = showDone
? <Button icon="check circle" title={doneButtonLabel} ariaLabel={doneButtonLabel} text={lf("Done")} onClick={onTutorialComplete} />
const nextButton = isDone
? hideDone ? null : <Button icon="check circle" title={doneButtonLabel} ariaLabel={doneButtonLabel} text={lf("Done")} onClick={onTutorialComplete} />
: <Button icon="arrow circle right" title={nextButtonLabel} ariaLabel={nextButtonLabel} disabled={!showNext} text={lf("Next")} onClick={() => validateTutorialStep()} />;

const stepCounter = <TutorialStepCounter
Expand All @@ -247,6 +248,7 @@ export function TutorialContainer(props: TutorialContainerProps) {
totalSteps={steps.length}
title={name}
isHorizontal={isHorizontal}
hideDone={hideDone}
setTutorialStep={handleStepCounterSetStep}
onDone={onTutorialComplete} />;
const hasHint = !!hintMarkdown;
Expand Down Expand Up @@ -290,4 +292,4 @@ export function TutorialContainer(props: TutorialContainerProps) {
<MarkedContent markdown={currentStepInfo.contentMd} parent={parent} />
</Modal>}
</div>
}
}
8 changes: 5 additions & 3 deletions webapp/src/components/tutorial/TutorialStepCounter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface TutorialStepCounterProps {
totalSteps: number;
title?: string;
isHorizontal?: boolean;
hideDone?: boolean;
setTutorialStep: (step: number) => void;
onDone: () => void;
}
Expand Down Expand Up @@ -42,6 +43,7 @@ export function TutorialStepCounter(props: TutorialStepCounterProps) {

const lastStep = currentStep == totalSteps - 1;
const nextButtonTitle = lastStep ? lf("Finish the tutorial.") : lf("Go to the next step of the tutorial.");
const showNextButton = !lastStep || !props.hideDone;

return <div className="tutorial-step-counter">
<div className="tutorial-step-label">
Expand All @@ -68,13 +70,13 @@ export function TutorialStepCounter(props: TutorialStepCounterProps) {
label={stepNum === currentStep ? `${stepNum + 1}` : undefined}
/>
})}
<Button
{showNextButton && <Button
className={props.isHorizontal ? "ui button counter-next-button" : "square-button"}
leftIcon={`icon ${lastStep ? "check" : props.isHorizontal ? "arrow circle right" : "right chevron"}`}
onClick={lastStep ? props.onDone : handleNextStep}
aria-label={nextButtonTitle}
title={nextButtonTitle}
label={props.isHorizontal ? lastStep ? lf("Done") : lf("Next") : ""} />
label={props.isHorizontal ? lastStep ? lf("Done") : lf("Next") : ""} />}
</div>
</div>
}
}
3 changes: 2 additions & 1 deletion webapp/src/tutorial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -674,9 +674,10 @@ export class TutorialCard extends data.Component<TutorialCardProps, TutorialCard
const currentStep = tutorialStep;
const maxSteps = tutorialStepInfo.length;
const hideIteration = metadata && metadata.hideIteration;
const hideDone = metadata && metadata.hideDone;
const hasPrevious = tutorialReady && currentStep != 0 && !hideIteration;
const hasNext = tutorialReady && currentStep != maxSteps - 1 && !hideIteration;
const hasFinish = !lockedEditor && currentStep == maxSteps - 1 && !hideIteration;
const hasFinish = !lockedEditor && currentStep == maxSteps - 1 && !hideIteration && !hideDone;
const hasHint = this.hasHint();
const tutorialCardContent = stepInfo.headerContentMd;
const showDialog = stepInfo.showDialog;
Expand Down

0 comments on commit e3e9ec7

Please sign in to comment.