Skip to content

Commit

Permalink
Merge pull request #2331 from codecrafters-io/reduce-previous-steps-i…
Browse files Browse the repository at this point in the history
…ncomplete-handling

Only show previous steps incomplete modal for instructions & setup
  • Loading branch information
rohitpaulk authored Oct 17, 2024
2 parents 8d50a7d + 56dffdf commit ac1e7e8
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 115 deletions.
17 changes: 17 additions & 0 deletions app/components/course-page/previous-steps-incomplete-overlay.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<BlurredOverlay
@isBlurred={{this.shouldShowModal}}
{{did-update this.handleStepIdUpdated @currentStep.id}}
@overlayClass="bg-gray-200 bg-opacity-20 dark:bg-gray-800 dark:bg-opacity-20"
...attributes
>
<:content>
{{yield}}
</:content>
<:overlay>
<CoursePage::PreviousStepsIncompleteModal
class="mt-8 mx-3 md:mx-6"
@onClose={{this.handleModalDismissed}}
@activeStep={{this.coursePageState.activeStep}}
/>
</:overlay>
</BlurredOverlay>
55 changes: 55 additions & 0 deletions app/components/course-page/previous-steps-incomplete-overlay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';
import Component from '@glimmer/component';
import type CoursePageStateService from 'codecrafters-frontend/services/course-page-state';
import { Step } from 'codecrafters-frontend/utils/course-page-step-list';

interface Signature {
Element: HTMLDivElement;

Args: {
currentStep: Step;
};

Blocks: {
default: [];
};
}

export default class PreviousStepsIncompleteOverlayComponent extends Component<Signature> {
@tracked modalWasDismissed = false;
@tracked lastSeenStepId: string | null = null;

@service declare coursePageState: CoursePageStateService;

get shouldShowModal(): boolean {
// This _shouldn't_ happen as long as we're always rendered in the course page, but let's be safe
if (!this.coursePageState.activeStep) {
return false;
}

return !this.modalWasDismissed && this.args.currentStep.status === 'locked';
}

@action
handleModalDismissed() {
this.modalWasDismissed = true;
}

@action
handleStepIdUpdated() {
if (this.args.currentStep.id === this.lastSeenStepId) {
return;
}

this.lastSeenStepId = this.args.currentStep.id;
this.modalWasDismissed = false;
}
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
'CoursePage::PreviousStepsIncompleteOverlay': typeof PreviousStepsIncompleteOverlayComponent;
}
}
18 changes: 1 addition & 17 deletions app/components/course-page/step-content.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,5 @@
/>
{{/if}}

<BlurredOverlay
@isBlurred={{this.shouldShowPreviousStepsIncompleteModal}}
@overlayClass="bg-gray-200 bg-opacity-20 dark:bg-gray-800 dark:bg-opacity-20"
class="px-3 md:px-6 lg:px-10"
{{did-update this.handleStepIdUpdated @step.id}}
>
<:content>
{{yield}}
</:content>
<:overlay>
<CoursePage::PreviousStepsIncompleteModal
class="mt-8 mx-3 md:mx-6"
@onClose={{this.handlePreviousStepsIncompleteModalDismissed}}
@activeStep={{this.coursePageState.activeStep}}
/>
</:overlay>
</BlurredOverlay>
{{yield}}
</div>
5 changes: 5 additions & 0 deletions app/controllers/course/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import type { ModelType } from 'codecrafters-frontend/routes/course/setup';
import type CoursePageStateService from 'codecrafters-frontend/services/course-page-state';
import type { Step } from 'codecrafters-frontend/utils/course-page-step-list';

export default class CourseSetupController extends Controller {
declare model: ModelType;

@service declare coursePageState: CoursePageStateService;

get currentStep(): Step {
return this.coursePageState.activeStep as Step;
}
}
2 changes: 1 addition & 1 deletion app/templates/course/base-stages-completed.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="pt-8 pb-16">
<div class="pt-8 pb-16 px-3 md:px-6 lg:px-10">
<CoursePage::BaseStagesCompletedCard @repository={{@model.activeRepository}} />
</div>
2 changes: 1 addition & 1 deletion app/templates/course/completed.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{! @glint-nocheck: not typesafe yet !}}
<div class="pt-8 pb-16">
<div class="pt-8 pb-16 px-3 md:px-6 lg:px-10">
<CoursePage::CourseCompletedCard @repository={{@model.activeRepository}} />
</div>
2 changes: 1 addition & 1 deletion app/templates/course/extension-completed.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="pt-8 pb-16">
<div class="pt-8 pb-16 px-3 md:px-6 lg:px-10">
<CoursePage::ExtensionCompletedCard @repository={{@model.activeRepository}} @extension={{@model.extension}} />
</div>
2 changes: 1 addition & 1 deletion app/templates/course/introduction.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="w-full pt-8 pb-32">
<div class="w-full pt-8 pb-32 px-3 md:px-6 lg:px-10">
{{#if this.authenticator.currentUser.pendingProductWalkthroughFeatureSuggestion}}
<ProductWalkthroughFeatureSuggestion
@featureSuggestion={{this.authenticator.currentUser.pendingProductWalkthroughFeatureSuggestion}}
Expand Down
8 changes: 5 additions & 3 deletions app/templates/course/setup.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<div class="w-full pt-8 pb-32">
<CoursePage::SetupStep::RepositorySetupCard @repository={{@model.activeRepository}} />
</div>
<CoursePage::PreviousStepsIncompleteOverlay @currentStep={{this.currentStep}}>
<div class="w-full pt-8 pb-32 px-3 md:px-6 lg:px-10">
<CoursePage::SetupStep::RepositorySetupCard @repository={{@model.activeRepository}} />
</div>
</CoursePage::PreviousStepsIncompleteOverlay>
2 changes: 1 addition & 1 deletion app/templates/course/stage/code-examples.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div
class="pt-8 pb-32"
class="pt-8 pb-32 px-3 md:px-6 lg:px-10"
{{did-update (fn (mut this.stageIncompleteModalWasDismissed) false) this.courseStage}}
{{did-update this.loadSolutions this.courseStage}}
{{did-insert this.loadSolutions}}
Expand Down
2 changes: 1 addition & 1 deletion app/templates/course/stage/concepts.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="pt-8 pb-32" data-test-concepts-tab>
<div class="pt-8 pb-32 px-3 md:px-6 lg:px-10" data-test-concepts-tab>
<AlertWithIcon class="mb-6">
Concepts are interactive tutorials that teach you fundamental concepts related to this challenge.
<br />
Expand Down
174 changes: 88 additions & 86 deletions app/templates/course/stage/instructions.hbs
Original file line number Diff line number Diff line change
@@ -1,101 +1,103 @@
<div class="pt-6 pb-32">
{{#if this.shouldShowUpgradePrompt}}
<CoursePage::CourseStageStep::UpgradePrompt @featureSlugToHighlight="content" class="mb-6" />
{{/if}}
<CoursePage::PreviousStepsIncompleteOverlay @currentStep={{this.currentStep}}>
<div class="pt-6 pb-32 px-3 md:px-6 lg:px-10">
{{#if this.shouldShowUpgradePrompt}}
<CoursePage::CourseStageStep::UpgradePrompt @featureSlugToHighlight="content" class="mb-6" />
{{/if}}

{{#if this.shouldShowFeedbackPrompt}}
<CoursePage::CourseStageStep::FeedbackPrompt
@courseStage={{@model.courseStage}}
@repository={{@model.activeRepository}}
@onSubmit={{this.handleStageFeedbackSubmitted}}
class="mb-6"
/>
{{/if}}

{{#if (gt this.badgeAwards.length 0)}}
<CoursePage::CourseStageStep::EarnedBadgeNotice @badgeAwards={{this.badgeAwards}} class="mb-6" />
{{/if}}
{{#if this.shouldShowFeedbackPrompt}}
<CoursePage::CourseStageStep::FeedbackPrompt
@courseStage={{@model.courseStage}}
@repository={{@model.activeRepository}}
@onSubmit={{this.handleStageFeedbackSubmitted}}
class="mb-6"
/>
{{/if}}

{{#if @model.courseStage.isFirst}}
<CoursePage::CourseStageStep::FirstStageTutorialCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} class="mb-6" />
{{/if}}
{{#if (gt this.badgeAwards.length 0)}}
<CoursePage::CourseStageStep::EarnedBadgeNotice @badgeAwards={{this.badgeAwards}} class="mb-6" />
{{/if}}

{{#if @model.courseStage.isSecond}}
<CoursePage::CourseStageStep::SecondStageInstructionsCard
@repository={{@model.activeRepository}}
@courseStage={{@model.courseStage}}
class="mb-6"
/>
{{/if}}
{{#if @model.courseStage.isFirst}}
<CoursePage::CourseStageStep::FirstStageTutorialCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} class="mb-6" />
{{/if}}

{{#if this.shouldShowTestRunnerCard}}
<div class="mb-6">
<CoursePage::CourseStageStep::TestRunnerCard
@isCollapsible={{or this.shouldSuppressTestRunnerCardExpands (not-eq this.currentStep.testsStatus "passed")}}
{{#if @model.courseStage.isSecond}}
<CoursePage::CourseStageStep::SecondStageInstructionsCard
@repository={{@model.activeRepository}}
@stage={{@model.courseStage}}
@onExpand={{if this.shouldSuppressTestRunnerCardExpands this.handleTestRunnerCardExpandedOnFirstStage undefined}}
@courseStage={{@model.courseStage}}
class="mb-6"
/>
{{/if}}

{{#if this.shouldSuppressTestRunnerCardExpands}}
<EmberPopover @popperContainer="body">
<div class="prose prose-sm prose-invert text-white">
{{#if (eq this.currentStep.testsStatus "failed")}}
<p>
This failure is expected! Check the
<a href="#first-stage-tutorial-card">How to pass this stage</a>
section for instructions.
</p>
{{else}}
<p>
Check the
<a href="#first-stage-tutorial-card">How to pass this stage</a>
section for instructions.
</p>
{{/if}}
</div>
</EmberPopover>
{{/if}}
</div>
{{/if}}
{{#if this.shouldShowTestRunnerCard}}
<div class="mb-6">
<CoursePage::CourseStageStep::TestRunnerCard
@isCollapsible={{or this.shouldSuppressTestRunnerCardExpands (not-eq this.currentStep.testsStatus "passed")}}
@repository={{@model.activeRepository}}
@stage={{@model.courseStage}}
@onExpand={{if this.shouldSuppressTestRunnerCardExpands this.handleTestRunnerCardExpandedOnFirstStage undefined}}
/>

{{! TODO: Bring this back? }}
{{!-- {{#if this.shouldShowPrerequisites}}
<CoursePage::CourseStageStep::PrerequisitesCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} class="mb-6" />
{{/if}} --}}
{{#if this.shouldSuppressTestRunnerCardExpands}}
<EmberPopover @popperContainer="body">
<div class="prose prose-sm prose-invert text-white">
{{#if (eq this.currentStep.testsStatus "failed")}}
<p>
This failure is expected! Check the
<a href="#first-stage-tutorial-card">How to pass this stage</a>
section for instructions.
</p>
{{else}}
<p>
Check the
<a href="#first-stage-tutorial-card">How to pass this stage</a>
section for instructions.
</p>
{{/if}}
</div>
</EmberPopover>
{{/if}}
</div>
{{/if}}

<CoursePage::CourseStageStep::YourTaskCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} />
{{! TODO: Bring this back? }}
{{!-- {{#if this.shouldShowPrerequisites}}
<CoursePage::CourseStageStep::PrerequisitesCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} class="mb-6" />
{{/if}} --}}

{{#if this.shouldShowLanguageGuide}}
<CoursePage::CourseStageStep::LanguageGuideCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} class="mt-6" />
{{/if}}
<CoursePage::CourseStageStep::YourTaskCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} />

<div data-percy-hints-section>
<div class="border-b dark:border-white/5 pb-2 mb-6 mt-8 flex items-center justify-between">
<h2 class="font-semibold text-lg text-gray-800 dark:text-gray-200">Hints</h2>
{{#if this.shouldShowLanguageGuide}}
<CoursePage::CourseStageStep::LanguageGuideCard @repository={{@model.activeRepository}} @courseStage={{@model.courseStage}} class="mt-6" />
{{/if}}

{{#if @model.activeRepository.language}}
<div class="flex items-center gap-1">
<span class="text-xs text-gray-500 mr-2">Filter by {{@model.activeRepository.language.name}}</span>
<Toggle @isOn={{this.commentListIsFilteredByLanguage}} {{on "click" this.handleCommentListFilterToggled}} />
<div data-percy-hints-section>
<div class="border-b dark:border-white/5 pb-2 mb-6 mt-8 flex items-center justify-between">
<h2 class="font-semibold text-lg text-gray-800 dark:text-gray-200">Hints</h2>

<EmberTooltip>
{{#if this.commentListIsFilteredByLanguage}}
You're currently viewing hints that are relevant to
{{@model.activeRepository.language.name}}. Turn this off to view hints for all languages.
{{else}}
You're currently viewing hints for all languages. Turn this on to filter hints that are relevant to
{{@model.activeRepository.language.name}}.
{{/if}}
</EmberTooltip>
</div>
{{/if}}
</div>
{{#if @model.activeRepository.language}}
<div class="flex items-center gap-1">
<span class="text-xs text-gray-500 mr-2">Filter by {{@model.activeRepository.language.name}}</span>
<Toggle @isOn={{this.commentListIsFilteredByLanguage}} {{on "click" this.handleCommentListFilterToggled}} />

<EmberTooltip>
{{#if this.commentListIsFilteredByLanguage}}
You're currently viewing hints that are relevant to
{{@model.activeRepository.language.name}}. Turn this off to view hints for all languages.
{{else}}
You're currently viewing hints for all languages. Turn this on to filter hints that are relevant to
{{@model.activeRepository.language.name}}.
{{/if}}
</EmberTooltip>
</div>
{{/if}}
</div>

<CoursePage::CommentList
@courseStage={{@model.courseStage}}
@language={{@model.activeRepository.language}}
@shouldFilterByLanguage={{this.commentListIsFilteredByLanguage}}
/>
<CoursePage::CommentList
@courseStage={{@model.courseStage}}
@language={{@model.activeRepository.language}}
@shouldFilterByLanguage={{this.commentListIsFilteredByLanguage}}
/>
</div>
</div>
</div>
</CoursePage::PreviousStepsIncompleteOverlay>
2 changes: 1 addition & 1 deletion app/templates/course/stage/screencasts.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="pt-8 pb-16" data-test-screencasts-tab>
<div class="pt-8 pb-16 px-3 md:px-6 lg:px-10" data-test-screencasts-tab>
<AlertWithIcon class="mb-6">
Screencasts are recordings of CodeCrafters users passing this stage. This is a beta feature, please send us
<div class="inline-flex">
Expand Down
2 changes: 0 additions & 2 deletions tests/acceptance/course-page/view-code-examples-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ module('Acceptance | course-page | view-code-examples', function (hooks) {
await courseOverviewPage.clickOnStartCourse();
await coursePage.sidebar.clickOnStepListItem('Respond to PING');
await coursePage.yourTaskCard.clickOnActionButton('Code Examples');
await coursePage.previousStepsIncompleteModal.clickOnJustExploringButton();

assert.strictEqual(coursePage.codeExamplesTab.solutionCards[0].changedFiles.length, 2, 'shows 2 changed files');
assert.strictEqual(coursePage.codeExamplesTab.solutionCards[0].unchangedFiles.length, 2, 'shows 2 unchanged files');
Expand Down Expand Up @@ -594,7 +593,6 @@ module('Acceptance | course-page | view-code-examples', function (hooks) {
await catalogPage.clickOnCourse('Build your own Redis');
await courseOverviewPage.clickOnStartCourse();
await coursePage.sidebar.clickOnStepListItem('Implement the ECHO command');
await coursePage.previousStepsIncompleteModal.clickOnJustExploringButton();
await coursePage.yourTaskCard.clickOnActionButton('Code Examples');

await coursePage.codeExamplesTab.languageDropdown.toggle();
Expand Down

0 comments on commit ac1e7e8

Please sign in to comment.