Skip to content

Commit

Permalink
Add classification by browsing
Browse files Browse the repository at this point in the history
  • Loading branch information
cqnykamp committed Aug 24, 2024
1 parent 25c9188 commit e4032be
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 83 deletions.
177 changes: 157 additions & 20 deletions client/src/Tools/_framework/ToolPanels/ClassificationSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,17 @@ import {
HStack,
Tooltip,
Spinner,
CardBody,
Card,
CardHeader,
Button,
} from "@chakra-ui/react";
import AsyncSelect from "react-select/async";
import { ContentClassification, ContentStructure } from "../../../_utils/types";
import {
ClassificationSystemTree,
ContentClassification,
ContentStructure,
} from "../../../_utils/types";

export async function classificationSettingsActions({
formObj,
Expand Down Expand Up @@ -91,19 +99,23 @@ export function ClassificationSettings({
setClassifyItemRemoveSpinner(0);
}, [contentData]);

let [allClassifications, setAllClassifications] = useState();
let [allClassifications, setAllClassifications] = useState<
ClassificationSystemTree[]
>([]);
useEffect(() => {
async function getAllClassifications() {
const { data } = await axios.get(
`/api/getContributorHistory/${contentData.id}`,
);
}

if (!contentData.isFolder) {
getAllClassifications();
async function setClassifications() {
const { data } = await axios.get(`/api/getAllClassificationInfo`);
setAllClassifications(data);
}
setClassifications();
}, []);

let [selectedSystem, setSelectedSystem] = useState<number | null>(null);
let [selectedCategory, setSelectedCategory] = useState<number | null>(null);
let [selectedSubCategory, setSelectedSubCategory] = useState<number | null>(
null,
);

return (
<>
<AlertQueue alerts={alerts} />
Expand All @@ -117,7 +129,9 @@ export function ClassificationSettings({
<Text>Existing Classifications</Text>

{contentData.classifications.length === 0 ? (
<Text as="i" mt="-5" ml='3'>None added yet.</Text>
<Text as="i" mt="-5" ml="3">
None added yet.
</Text>
) : (
<Accordion allowMultiple>
{contentData.classifications.map((classification, i) => (
Expand All @@ -128,7 +142,10 @@ export function ClassificationSettings({
<HStack flex="1" textAlign="left" direction={"row"}>
;<Text as="b">{classification.code}</Text>
<Text fontSize={"small"} pt="2px">
{classification.subCategory.category.system.name}
{
classification.subCategory.category.system
.name
}
</Text>
</HStack>
<AccordionIcon marginLeft="7px" />
Expand Down Expand Up @@ -165,13 +182,21 @@ export function ClassificationSettings({
<AccordionPanel>
<Text>
<Text as="b">
{classification.subCategory.category.system.categoryLabel}:{" "}
{
classification.subCategory.category.system
.categoryLabel
}
:{" "}
</Text>
{classification.subCategory.category.category}
</Text>
<Text>
<Text as="b">
{classification.subCategory.category.system.subCategoryLabel}:{" "}
{
classification.subCategory.category.system
.subCategoryLabel
}
:{" "}
</Text>
{classification.subCategory.subCategory}
</Text>
Expand All @@ -187,9 +212,111 @@ export function ClassificationSettings({

<Text>Add a Classification</Text>
<Box rowGap={2}>
<Select placeholder="Choose a system"></Select>
<Select placeholder="-" isDisabled></Select>
<Select placeholder="-" isDisabled></Select>
<Select
placeholder="Choose a system"
onChange={(event) => {
if (event.target.value) {
setSelectedSystem(Number(event.target.value));
} else {
setSelectedSystem(null);
}
setSelectedCategory(null);
setSelectedSubCategory(null);
}}
>
{allClassifications.map((system, i) => (
<option value={i}>{system.name}</option>
))}
</Select>

<Select
value={selectedCategory ?? ""}
placeholder={
selectedSystem === null
? "-"
: `Choose a ${allClassifications[selectedSystem].categoryLabel}`
}
isDisabled={selectedSystem === null}
onChange={(event) => {
if (event.target.value) {
setSelectedCategory(Number(event.target.value));
} else {
setSelectedCategory(null);
}
setSelectedSubCategory(null);
}}
>
{selectedSystem !== null
? allClassifications[selectedSystem].categories.map(
(category, i) => (
<option value={i}>{category.category}</option>
),
)
: null}
</Select>

<Select
value={selectedSubCategory ?? ""}
placeholder={
selectedCategory === null
? "-"
: `Choose a ${allClassifications[selectedSystem!].subCategoryLabel}`
}
isDisabled={selectedCategory === null}
onChange={(event) => {
if (event.target.value) {
setSelectedSubCategory(Number(event.target.value));
} else {
setSelectedSubCategory(null);
}
}}
>
{selectedCategory !== null
? allClassifications[selectedSystem!].categories[
selectedCategory
].subCategories.map((subCategory, i) => (
<option value={i}>{subCategory.subCategory}</option>
))
: null}
</Select>
{selectedSubCategory !== null
? allClassifications[selectedSystem!].categories[
selectedCategory!
].subCategories[selectedSubCategory].classifications.map(
(classification) => (
<Card>
<CardBody>
<Flex>
<Heading size="sm">{classification.code}</Heading>
<Spacer />
{contentData.classifications
.map((c) => c.id)
.includes(classification.id) ? (
<Text as="i">Already added</Text>
) : (
<Button
size="sm"
onClick={() => {
fetcher.submit(
{
_action: "add content classification",
activityId: id,
classificationId: classification.id,
},
{ method: "post" },
);
}}
>
Add
</Button>
)}
</Flex>
<Text>{classification.description}</Text>
</CardBody>
</Card>
),
)
: null}
</Box>

<HStack>
Expand Down Expand Up @@ -228,7 +355,9 @@ export function ClassificationSettings({
>
{val.label.code +
(val.label.subCategory.category.category
? " (" + val.label.subCategory.category.category + ")"
? " (" +
val.label.subCategory.category.category +
")"
: "")}
</Highlight>
</Heading>
Expand All @@ -244,7 +373,11 @@ export function ClassificationSettings({
</Flex>
<Text>
<Text as="i">
{val.label.subCategory.category.system.categoryLabel}:
{
val.label.subCategory.category.system
.categoryLabel
}
:
</Text>{" "}
<Highlight
query={classifySelectorInput.split(" ")}
Expand All @@ -255,7 +388,11 @@ export function ClassificationSettings({
</Text>
<Text>
<Text as="i">
{val.label.subCategory.category.system.subCategoryLabel}:
{
val.label.subCategory.category.system
.subCategoryLabel
}
:
</Text>{" "}
<Highlight
query={classifySelectorInput.split(" ")}
Expand Down
29 changes: 20 additions & 9 deletions client/src/Tools/_framework/ToolPanels/ContentSettingsDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ import {
SupportFilesControls,
} from "./SupportFilesControls";
import { ContentStructure, DoenetmlVersion } from "../../../_utils/types";
import { ClassificationSettings, classificationSettingsActions } from "./ClassificationSettings";
import {
ClassificationSettings,
classificationSettingsActions,
} from "./ClassificationSettings";
import axios from "axios";

export async function contentSettingsActions({
formObj,
Expand Down Expand Up @@ -117,7 +121,12 @@ export function ContentSettingsDrawer({
<Tabs index={tabIndex} onChange={(index) => setTabIndex(index)}>
<TabList>
<Tab data-test="General Tab">General</Tab>
<Tab data-test="Classifications">Classifications ({contentData.classifications.length})</Tab>

{!contentData.isFolder ? (
<Tab data-test="Classifications">
Classifications ({contentData.classifications.length})
</Tab>
) : null}
{haveSupportingFiles ? (
<Tab data-test="Files Tab">Support Files</Tab>
) : null}
Expand All @@ -132,13 +141,15 @@ export function ContentSettingsDrawer({
allDoenetmlVersions={allDoenetmlVersions}
/>
</TabPanel>
<TabPanel>
<ClassificationSettings
fetcher={fetcher}
id={id}
contentData={contentData}
/>
</TabPanel>
{!contentData.isFolder ? (
<TabPanel>
<ClassificationSettings
fetcher={fetcher}
id={id}
contentData={contentData}
/>
</TabPanel>
) : null}
{haveSupportingFiles ? (
<TabPanel>
<SupportFilesControls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,6 @@ export function GeneralContentControls({
let [imagePath, setImagePath] = useState(dataImagePath);
let [alerts, setAlerts] = useState<Alert[]>([]);

let [classifySelectorInput, setClassifySelectorInput] = useState<string>("");
const classificationsAlreadyAdded = contentData.classifications.map(
(c2) => c2.id,
);

// let learningOutcomesInit = activityData.learningOutcomes;
// if (learningOutcomesInit == null) {
// learningOutcomesInit = [""];
Expand Down Expand Up @@ -462,7 +457,6 @@ export function GeneralContentControls({
<input type="hidden" name="imagePath" value={imagePath ?? undefined} />
<input type="hidden" name="_action" value="update general" />
<input type="hidden" name="id" value={id} />

</Form>
</>
);
Expand Down
21 changes: 21 additions & 0 deletions client/src/_utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,24 @@ export type DocRemixItem = {
activityName: string;
owner: UserInfo;
};


export type ClassificationSystemTree = {
id: number;
name: string;
categoryLabel: string;
subCategoryLabel: string;
categories: {
id: number;
category: string;
subCategories: {
id: number;
subCategory: string;
classifications: {
id: number;
code: string;
description: string;
}[]
}[]
}[]
};
22 changes: 12 additions & 10 deletions server/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,16 @@ async function main() {
"Count to 100 by ones and by tens.",
commonCoreCardinalityId,
);
await upsertClassification(
"K.CC.2",
"Count forward beginning from a given number within the known sequence (instead of having to begin at 1).",
commonCoreCardinalityId,
);
await upsertClassification(
"K.CC.3",
"Write numbers from 0 to 20. Represent a number of objects with a written numeral 0-20 (with 0 representing a count of no objects).",
commonCoreCardinalityId,
);
await upsertClassification(
"K.OA.1",
"Represent addition and subtraction with objects, fingers, mental images, drawings (Drawings need not show details, but should show the mathematics in the problem.(This applies wherever drawings are mentioned in the Standards.)), sounds (e.g., claps), acting out situations, verbal explanations, expressions, or equations.",
Expand All @@ -173,14 +183,8 @@ async function main() {
"Grade",
"Standard",
);
const mnEighthId = await upsertClassificationCategory(
"8",
mnId,
);
const mnNinthId = await upsertClassificationCategory(
"9",
mnId,
);
const mnEighthId = await upsertClassificationCategory("8", mnId);
const mnNinthId = await upsertClassificationCategory("9", mnId);
const mnFuncId = await upsertClassificationSubCategory(
"Understand the concept of function in real-world and mathematical situations, and distinguish between linear and nonlinear functions.",
mnEighthId,
Expand All @@ -200,8 +204,6 @@ async function main() {
mnProbabilityId,
);



await prisma.licenses.upsert({
where: { code: "CCBYSA" },
update: {
Expand Down
Loading

0 comments on commit e4032be

Please sign in to comment.