Skip to content

Commit

Permalink
Llad 2 (#141)
Browse files Browse the repository at this point in the history
* fix(AssetTags): [wip] asset tag keys

* feat(AssetTags): separate AssetTagKeys to separate collection

* fix(AssetTags): type errors
  • Loading branch information
jakeaturner committed Nov 1, 2023
1 parent aa77b5f commit 74d6b82
Show file tree
Hide file tree
Showing 22 changed files with 911 additions and 102 deletions.
4 changes: 2 additions & 2 deletions client/src/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import axios from "axios";
import AuthHelper from "./components/util/AuthHelper";
import { AssetTagFramework, Book, ConductorBaseResponse, Homework, Project, ProjectFile, User } from "./types";
import { AssetTagFramework, AssetTagFrameworkWithKeys, Book, ConductorBaseResponse, Homework, Project, ProjectFile, User } from "./types";
import { ProjectFileWProjectID } from "./types/Project";

/**
Expand Down Expand Up @@ -40,7 +40,7 @@ class API {
const res = await axios.get<{
err: boolean;
errMsg?: string;
framework: AssetTagFramework;
framework: AssetTagFrameworkWithKeys
}>(`/assettagframeworks/${id}`);
return res;
}
Expand Down
50 changes: 39 additions & 11 deletions client/src/components/FilesManager/EditFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import SelectFramework from "./SelectFramework";
import api from "../../api";
import { getInitValueFromTemplate } from "../../utils/assetHelpers";
import { RenderTagInput } from "./RenderTagInput";
import { AssetTagTemplate, AssetTagValue } from "../../types/AssetTagging";
import { isAssetTagFramework } from "../../utils/typeHelpers";
import { AssetTagTemplate, AssetTagValue, AssetTagWithKey } from "../../types/AssetTagging";
import { isAssetTagFramework, isAssetTagKeyObject } from "../../utils/typeHelpers";

interface EditFileModalProps extends ModalProps {
show: boolean;
Expand Down Expand Up @@ -95,7 +95,18 @@ const EditFile: React.FC<EditFileModalProps> = ({
}

const fileData = res.data.files[res.data.files.length - 1]; // Target file should be last in array
reset(fileData);
const parsedExistingTags: AssetTag[] = fileData.tags?.map(
(t: AssetTagWithKey) => {
return {
...t,
key: t.key.title,
};
}
);
reset({
...fileData,
tags: parsedExistingTags,
});
setIsFolder(fileData.storageType !== "file");
} catch (err) {
handleGlobalError(err);
Expand Down Expand Up @@ -145,7 +156,19 @@ const EditFile: React.FC<EditFileModalProps> = ({
throw new Error(res.data.errMsg);
}

setSelectedFramework(res.data.framework);
const parsed: AssetTagTemplate[] = res.data.framework.templates.map(
(t) => {
return {
...t,
key: t.key.title,
};
}
);

setSelectedFramework({
...res.data.framework,
templates: parsed,
});
genTagsFromFramework();
} catch (err) {
handleGlobalError(err);
Expand All @@ -164,35 +187,40 @@ const EditFile: React.FC<EditFileModalProps> = ({

if (existingTags && existingTags.length > 0) {
filtered = selectedFramework.templates.filter(
(t) => !existingTags.find((tag) => tag.title === t.title)
(t) => !existingTags.find((tag) => {
if(isAssetTagKeyObject(tag.key)){
return tag.key.title === t.key
}
return tag.key === t.key
})
);
} else {
filtered = selectedFramework.templates;
}

filtered.forEach((t) => {
addTag({
title: t.title,
key: t.key,
value: getInitValueFromTemplate(t),
framework: selectedFramework,
});
});
}

function addTag({
title,
key,
value,
framework,
}: {
title?: string;
key?: string;
value?: AssetTagValue;
framework?: AssetTagFramework;
}) {
if (isFolder) return; // No asset tags for folders
append(
{
uuid: crypto.randomUUID(), // Random UUID for new tags, will be replaced with real UUID server-side on save
title: title ?? "",
key: key ?? "",
value: value ?? "",
framework: framework ?? undefined,
isDeleted: false,
Expand Down Expand Up @@ -254,7 +282,7 @@ const EditFile: React.FC<EditFileModalProps> = ({
<Table.Cell>
{tag.framework ? (
<div className="flex flex-col">
<p>{tag.title}</p>
<p>{isAssetTagKeyObject(tag.key) ? tag.key.title : tag.key}</p>
{/* {isAssetTagFramework(tag.framework) && (
<div className="mt-1">
<Label size="mini">
Expand All @@ -265,7 +293,7 @@ const EditFile: React.FC<EditFileModalProps> = ({
</div>
) : (
<CtlTextInput
name={`tags.${index}.title`}
name={`tags.${index}.key`}
control={control}
fluid
/>
Expand Down
44 changes: 29 additions & 15 deletions client/src/components/FilesManager/RenderAssetTags.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
import { Label } from "semantic-ui-react";
import { AssetTag, ProjectFile } from "../../types";
import { truncateString } from "../util/HelperFunctions";
import { SemanticCOLORSArray } from "../../utils/misc";
import { isAssetTagKeyObject } from "../../utils/typeHelpers";

const RenderAssetTags: React.FC<{ file: ProjectFile }> = ({ file }) => {
const sortedTags = file.tags?.sort((a, b) => {
if (isAssetTagKeyObject(a.key) && isAssetTagKeyObject(b.key)) {
return a.key.title.localeCompare(b.key.title);
}
return 0;
});

function getLabelValue(tag: AssetTag) {
const text = tag.title + ": " + tag.value.toString();
const title = isAssetTagKeyObject(tag.key) ? tag.key.title : tag.key;
const text = title + ": " + tag.value.toString();
const truncated = truncateString(text, 20);
return truncated;
}

// Get a random color from SemanticCOLORSArray
function getLabelColor() {
// Remove grey from the array, reserve it for the "more" truncation label
const colors = SemanticCOLORSArray.filter((color) => color !== "grey");
const randomElement =
colors[
Math.floor(Math.random() * colors.length)
];
return randomElement;
function getLabelColor(tag: AssetTag) {
if(tag.key && isAssetTagKeyObject(tag.key)) {
return tag.key.hex;
}
return "grey";
}

return (
<div className="asset-tag-container">
{file.tags?.slice(0, 5).map((tag) => (
<Label color={getLabelColor()} size="tiny" key={tag.uuid}>
{!sortedTags ||
(sortedTags.length === 0 && (
<span className="muted-text italic">No associated tags</span>
))}
{sortedTags?.slice(0, 5).map((tag) => (
<Label style={
{
backgroundColor: getLabelColor(tag).toString(),
borderColor: getLabelColor(tag).toString(),
color: "white"
}
} size="tiny" key={tag.uuid}>
{getLabelValue(tag)}
</Label>
))}
{file.tags && file.tags?.length > 5 ? (
{sortedTags && sortedTags?.length > 5 ? (
<Label color="grey" size="tiny">
+{file.tags?.length - 5} more
+{sortedTags?.length - 5} more
</Label>
) : (
<></>
Expand Down
9 changes: 7 additions & 2 deletions client/src/components/FilesManager/RenderTagInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
ProjectFile,
} from "../../types";
import CtlTextInput from "../ControlledInputs/CtlTextInput";
import { isAssetTagFramework } from "../../utils/typeHelpers";
import {
isAssetTagFramework,
isAssetTagKeyObject,
} from "../../utils/typeHelpers";
import { Dropdown } from "semantic-ui-react";

interface RenderTagInputProps {
Expand Down Expand Up @@ -63,7 +66,9 @@ export const RenderTagInput: React.FC<RenderTagInputProps> = ({
}

const templateInFramework = tag.framework.templates.find(
(template) => template.title === tag.title
(template) =>
template.title ===
(isAssetTagKeyObject(tag.key) ? tag.key.title : tag.key)
);

if (templateInFramework) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import {
Button,
Dropdown,
Icon,
Input,
Modal,
ModalProps,
Select,
Table,
} from "semantic-ui-react";
import {
AssetTagTemplate,
AssetTagFramework,
AssetTagTemplate,
AssetTagTemplateValueTypeOptions,
} from "../../../types";
import CtlCheckbox from "../../ControlledInputs/CtlCheckbox";
import CtlTextInput from "../../ControlledInputs/CtlTextInput";
import "../../../styles/global.css";
import { isAssetTagTemplate } from "../../../utils/typeHelpers";
import {
isAssetTagKeyObject,
isAssetTagTemplate,
} from "../../../utils/typeHelpers";
import { useEffect, useState } from "react";
import CtlDropdown from "../../ControlledInputs/CtlDropdown";
import useGlobalError from "../../error/ErrorHooks";
import api from "../../../api";
import LoadingSpinner from "../../LoadingSpinner";
Expand Down Expand Up @@ -76,7 +76,22 @@ const ManageFrameworkModal: React.FC<ManageFrameworkModalProps> = ({
const res = await api.getFramework(id);
if (!res.data.framework) throw new Error("No framework found");

reset(res.data.framework);
const parsed: AssetTagTemplate[] = res.data.framework.templates.map(
(t) => {
return {
key: t.key.title,
valueType: t.valueType,
defaultValue: t.defaultValue,
options: t.options,
isDeleted: false,
};
}
);

reset({
...res.data.framework,
templates: parsed,
});
} catch (err) {
handleGlobalError(err);
} finally {
Expand Down Expand Up @@ -211,7 +226,7 @@ const ManageFrameworkModal: React.FC<ManageFrameworkModalProps> = ({
<Table.Cell>
<CtlTextInput
control={control}
name={`templates.${index}.title`}
name={`templates.${index}.key`}
fluid
/>
</Table.Cell>
Expand Down Expand Up @@ -270,7 +285,7 @@ const ManageFrameworkModal: React.FC<ManageFrameworkModalProps> = ({
onClick={() =>
append(
{
title: "",
key: "",
valueType: "text",
defaultValue: "",
isDeleted: false,
Expand Down
Loading

0 comments on commit 74d6b82

Please sign in to comment.