Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teacher Tool: Refactor Rubric to Checklist #9996

Merged
merged 9 commits into from
May 3, 2024
8 changes: 4 additions & 4 deletions teachertool/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { Toasts } from "./components/Toasts";
import { showToast } from "./transforms/showToast";
import { loadCatalogAsync } from "./transforms/loadCatalogAsync";
import { loadValidatorPlansAsync } from "./transforms/loadValidatorPlansAsync";
import { tryLoadLastActiveRubricAsync } from "./transforms/tryLoadLastActiveRubricAsync";
import { ImportRubricModal } from "./components/ImportRubricModal";
import { tryLoadLastActiveChecklistAsync } from "./transforms/tryLoadLastActiveChecklistAsync";
import { ImportChecklistModal } from "./components/ImportChecklistModal";
import { ConfirmationModal } from "./components/ConfirmationModal";
import { BlockPickerModal } from "./components/BlockPickerModal";
import { ScreenReaderAnnouncer } from "./components/ScreenReaderAnnouncer";
Expand All @@ -33,7 +33,7 @@ export const App = () => {
// Load catalog and validator plans into state.
await loadCatalogAsync();
await loadValidatorPlansAsync();
await tryLoadLastActiveRubricAsync();
await tryLoadLastActiveChecklistAsync();

// Test notification
showToast({
Expand All @@ -57,7 +57,7 @@ export const App = () => {
<>
<HeaderBar />
<MainPanel />
<ImportRubricModal />
<ImportChecklistModal />
<ConfirmationModal />
<BlockPickerModal />
<Toasts />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { useContext } from "react";
import { Strings } from "../constants";
import { AppStateContext } from "../state/appStateContext";
import { setRubricName } from "../transforms/setRubricName";
import { setChecklistName } from "../transforms/setChecklistName";
import { DebouncedInput } from "./DebouncedInput";
import { AddCriteriaButton } from "./AddCriteriaButton";
import css from "./styling/ActiveRubricDisplay.module.scss";
import css from "./styling/ActiveChecklistDisplay.module.scss";
import React from "react";
import { CriteriaTable } from "./CriteriaTable";

interface ActiveRubricDisplayProps {}
export const ActiveRubricDisplay: React.FC<ActiveRubricDisplayProps> = ({}) => {
interface ActiveChecklistDisplayProps {}
export const ActiveChecklistDisplay: React.FC<ActiveChecklistDisplayProps> = ({}) => {
const { state: teacherTool } = useContext(AppStateContext);

return (
<div className={css["rubric-display"]}>
<div className={css["rubric-name-input-container"]}>
<div className={css["checklist-display"]}>
<div className={css["checklist-name-input-container"]}>
<DebouncedInput
label={Strings.Name}
ariaLabel={Strings.Name}
onChange={setRubricName}
placeholder={Strings.RubricName}
initialValue={teacherTool.rubric.name}
onChange={setChecklistName}
placeholder={Strings.ChecklistName}
initialValue={teacherTool.checklist.name}
preserveValueOnBlur={true}
className={css["rubric-name-input"]}
className={css["checklist-name-input"]}
/>
</div>
<CriteriaTable />
Expand Down
8 changes: 4 additions & 4 deletions teachertool/src/components/CatalogOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useContext, useMemo, useState } from "react";
import { AppStateContext } from "../state/appStateContext";
import { addCriteriaToRubric } from "../transforms/addCriteriaToRubric";
import { addCriteriaToChecklist } from "../transforms/addCriteriaToChecklist";
import { CatalogCriteria } from "../types/criteria";
import { getCatalogCriteria } from "../state/helpers";
import { ReadOnlyCriteriaDisplay } from "./ReadonlyCriteriaDisplay";
Expand Down Expand Up @@ -75,7 +75,7 @@ const CatalogList: React.FC = () => {

const criteria = useMemo<CatalogCriteria[]>(
() => getCatalogCriteria(teacherTool),
[teacherTool.catalog, teacherTool.rubric]
[teacherTool.catalog, teacherTool.checklist]
);

function updateRecentlyAddedValue(id: string, value: NodeJS.Timeout | undefined) {
Expand All @@ -91,7 +91,7 @@ const CatalogList: React.FC = () => {
}

function onItemClicked(c: CatalogCriteria) {
addCriteriaToRubric([c.id]);
addCriteriaToChecklist([c.id]);

// Set a timeout to remove the recently added indicator
// and save it in the state.
Expand All @@ -109,7 +109,7 @@ const CatalogList: React.FC = () => {
return (
<div className={css["catalog-list"]}>
{criteria.map(c => {
const existingInstanceCount = teacherTool.rubric.criteria.filter(
const existingInstanceCount = teacherTool.checklist.criteria.filter(
i => i.catalogCriteriaId === c.id
).length;
const isMaxed = c.maxCount !== undefined && existingInstanceCount >= c.maxCount;
Expand Down
23 changes: 23 additions & 0 deletions teachertool/src/components/ChecklistPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { getCatalogCriteriaWithId } from "../state/helpers";
import { Checklist } from "../types/checklist";
import css from "./styling/ChecklistPreview.module.scss";

export interface IChecklistPreviewProps {
checklist: Checklist;
}

export const ChecklistPreview: React.FC<IChecklistPreviewProps> = ({ checklist }) => {
return (
<div className={css["container"]}>
<div className={css["checklist-header"]}>{checklist.name}</div>
{checklist.criteria.map((c, i) => {
const template = getCatalogCriteriaWithId(c.catalogCriteriaId)?.template;
return template ? (
<div key={i} className={css["checklist-criteria"]}>
{template}
</div>
) : null;
})}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
import * as React from "react";
import css from "./styling/RubricWorkspace.module.scss";
import css from "./styling/ChecklistWorkspace.module.scss";
import { useContext, useRef } from "react";
import { AppStateContext, stateAndDispatch } from "../state/appStateContext";
import { Toolbar } from "./Toolbar";
import { TabGroup, TabButton } from "./TabGroup";
import { TabPanel } from "./TabPanel";
import { HomeScreen } from "./HomeScreen";
import { EvalResultDisplay } from "./EvalResultDisplay";
import { ActiveRubricDisplay } from "./ActiveRubricDisplay";
import { ActiveChecklistDisplay } from "./ActiveChecklistDisplay";
import { MenuItem } from "react-common/components/controls/MenuDropdown";
import { TabName } from "../types";
import { runEvaluateAsync } from "../transforms/runEvaluateAsync";
import { writeRubricToFile } from "../services/fileSystemService";
import { writeChecklistToFile } from "../services/fileSystemService";
import { showModal } from "../transforms/showModal";
import { isProjectLoaded } from "../state/helpers";
import { setAutorun } from "../transforms/setAutorun";
import { Strings, Ticks } from "../constants";
import { resetRubricAsync } from "../transforms/resetRubricAsync";
import { resetChecklistAsync } from "../transforms/resetChecklistAsync";
import { PrintButton } from "./PrintButton";
import { ImportRubricOptions } from "../types/modalOptions";
import { ImportChecklistOptions } from "../types/modalOptions";

function handleImportRubricClicked() {
pxt.tickEvent(Ticks.ImportRubric);
showModal({ modal: "import-rubric" } as ImportRubricOptions);
function handleImportChecklistClicked() {
pxt.tickEvent(Ticks.ImportChecklist);
showModal({ modal: "import-checklist" } as ImportChecklistOptions);
}

function handleExportRubricClicked() {
pxt.tickEvent(Ticks.ExportRubric);
function handleExportChecklistClicked() {
pxt.tickEvent(Ticks.ExportChecklist);
const { state: teacherTool } = stateAndDispatch();
writeRubricToFile(teacherTool.rubric);
writeChecklistToFile(teacherTool.checklist);
}

async function handleNewRubricClickedAsync() {
pxt.tickEvent(Ticks.NewRubric);
await resetRubricAsync();
async function handleNewChecklistClickedAsync() {
pxt.tickEvent(Ticks.NewChecklist);
await resetChecklistAsync();
}

async function handleEvaluateClickedAsync() {
Expand All @@ -46,8 +46,8 @@ const WorkspaceTabButtons: React.FC = () => {

return (
<TabGroup>
<TabButton name="home">{lf("Home")}</TabButton>
<TabButton name="rubric">{lf("Rubric")}</TabButton>
<TabButton name="home">{Strings.Home}</TabButton>
<TabButton name="checklist">{Strings.Checklist}</TabButton>
<TabButton name="results" disabled={!isProjectLoaded(teacherTool)}>
{lf("Results")}
</TabButton>
Expand All @@ -65,8 +65,8 @@ const WorkspaceTabPanels: React.FC<WorkspaceTabPanelsProps> = ({ resultsRef }) =
<TabPanel name="home">
<HomeScreen />
</TabPanel>
<TabPanel name="rubric">
<ActiveRubricDisplay />
<TabPanel name="checklist">
<ActiveChecklistDisplay />
</TabPanel>
<TabPanel name="results">
<EvalResultDisplay resultsRef={resultsRef} />
Expand All @@ -79,25 +79,25 @@ function getActionMenuItems(tab: TabName): MenuItem[] {
const items: MenuItem[] = [];
switch (tab) {
case "home":
case "rubric":
case "checklist":
items.push(
{
title: Strings.NewRubric,
label: Strings.NewRubric,
ariaLabel: Strings.NewRubric,
onClick: handleNewRubricClickedAsync,
title: Strings.NewChecklist,
label: Strings.NewChecklist,
ariaLabel: Strings.NewChecklist,
onClick: handleNewChecklistClickedAsync,
},
{
title: Strings.ImportRubric,
label: Strings.ImportRubric,
ariaLabel: Strings.ImportRubric,
onClick: handleImportRubricClicked,
title: Strings.ImportChecklist,
label: Strings.ImportChecklist,
ariaLabel: Strings.ImportChecklist,
onClick: handleImportChecklistClicked,
},
{
title: Strings.ExportRubric,
label: Strings.ExportRubric,
ariaLabel: Strings.ExportRubric,
onClick: handleExportRubricClicked,
title: Strings.ExportChecklist,
label: Strings.ExportChecklist,
ariaLabel: Strings.ExportChecklist,
onClick: handleExportChecklistClicked,
}
);
break;
Expand Down Expand Up @@ -143,7 +143,7 @@ const WorkspaceToolbarButtons: React.FC<WorkspaceToolbarButtonsProps> = ({ resul
);
};

export const RubricWorkspace: React.FC = () => {
export const ChecklistWorkspace: React.FC = () => {
const resultsRef = useRef<HTMLDivElement>(null);
return (
<div className={css.panel}>
Expand Down
8 changes: 4 additions & 4 deletions teachertool/src/components/CriteriaTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useContext } from "react";
import { Strings } from "../constants";
import { AppStateContext } from "../state/appStateContext";
import { getCatalogCriteriaWithId } from "../state/helpers";
import { removeCriteriaFromRubric } from "../transforms/removeCriteriaFromRubric";
import { removeCriteriaFromChecklist } from "../transforms/removeCriteriaFromChecklist";
import { CriteriaInstance } from "../types/criteria";
import { classList } from "react-common/components/util";
import { Button } from "react-common/components/controls/Button";
Expand Down Expand Up @@ -39,7 +39,7 @@ const CriteriaInstanceRow: React.FC<CriteriaInstanceDisplayProps> = ({ criteriaI
className={css["delete-criteria-button"]}
title={Strings.Remove}
ariaLabel={Strings.Remove}
onClick={() => removeCriteriaFromRubric(criteriaInstance)}
onClick={() => removeCriteriaFromChecklist(criteriaInstance)}
/>
</div>
</div>
Expand All @@ -50,7 +50,7 @@ interface CriteriaTableProps {}
const CriteriaTableControl: React.FC<CriteriaTableProps> = ({}) => {
const { state: teacherTool } = useContext(AppStateContext);

return teacherTool.rubric.criteria?.length > 0 ? (
return teacherTool.checklist.criteria?.length > 0 ? (
<div className={css["criteria-table"]} role="table" aria-label={Strings.Criteria}>
<div role="rowgroup">
<div className={css["criteria-header"]} role="row">
Expand All @@ -67,7 +67,7 @@ const CriteriaTableControl: React.FC<CriteriaTableProps> = ({}) => {
</div>
</div>
<div className={css["criteria-table-body"]} role="rowgroup">
{teacherTool.rubric.criteria.map(criteriaInstance => {
{teacherTool.checklist.criteria.map(criteriaInstance => {
return (
<CriteriaInstanceRow criteriaInstance={criteriaInstance} key={criteriaInstance.instanceId} />
);
Expand Down
2 changes: 1 addition & 1 deletion teachertool/src/components/DragAndDropFileSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const DragAndDropFileSurface: React.FC<DragAndDropFileSurfaceProps> = ({
ref={fileInputRef}
className="hidden"
onChange={handleFileFromBrowse}
aria-label={Strings.SelectRubricFile}
aria-label={Strings.SelectChecklistFile}
accept=".json"
/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions teachertool/src/components/EvalResultDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const ResultsHeader: React.FC = () => {

return (
<div className={css["header"]}>
<div className={css["rubric-name"]}>
<h2>{teacherTool.rubric.name}</h2>
<div className={css["checklist-name"]}>
<h2>{teacherTool.checklist.name}</h2>
</div>
<div className={css["project-details"]}>
<div className={css["project-text"]}>
Expand Down
1 change: 0 additions & 1 deletion teachertool/src/components/HeaderBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import css from "./styling/HeaderBar.module.scss";
import { Button } from "react-common/components/controls/Button";
import { MenuBar } from "react-common/components/controls/MenuBar";
import { AppStateContext } from "../state/appStateContext";
import { getSafeRubricName } from "../state/helpers";
import { Ticks } from "../constants";

interface HeaderBarProps {}
Expand Down
Loading