Files
AutoGPT/autogpt_platform/frontend/src/lib/utils.ts
Swifty 1114b421d0 tweak(frontend): Update Blocks UI (#8190)
* Updated onOpenChange code style

* modifying how handle text is rendered

* Rounding input boxes

* Modifying layout of nodes

* formatting

* update edge start / end positions

* updated handle rendering

* moved outputs down and disabled toggle

* formatting

* update font

* update key name formatting

* modify layout of input items

* updated the add property button

* feat(platform): Sync on new UI design

* simplify UI

* block list add border and remove padding

* add highlight on navbar button

* Change block header so block costs line up correctly

* fix history type issue

* formatting

* tweaking css to hide white spot

* fixed white spot

* Added context menu

* Changed status badge color

* getting error colors just right

* Added a NodeOutputs component for rendering the outputs

* tidy up

* Change Add Item Button Color

* changed cursor on hover in block control panel

* formatting

* updated formatting of tutoral and tally buttons

* fix(platform): Fix text area input not updating input field

* Address comments

* Add missing color

* fix lint errors

* Cleanup context logic

* Make inputref reliable

* Update coloring

* fix(platform): Fix unexpected closing block list on tutorial

* Add X-scrolling

* Remove excessive shadows

* Remove another excessive shadows

* Another patch patch patch

* Add border on context menu

* Cleanup executions

* Cleanup executions

* Makr border darker

* Make border darker

* Fix input reset

---------

Co-authored-by: Zamil Majdy <zamil.majdy@agpt.co>
2024-10-03 12:16:25 +02:00

215 lines
5.7 KiB
TypeScript

import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import { Category } from "./autogpt-server-api/types";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
/** Derived from https://stackoverflow.com/a/7616484 */
export function hashString(str: string): number {
let hash = 0,
chr: number;
if (str.length === 0) return hash;
for (let i = 0; i < str.length; i++) {
chr = str.charCodeAt(i);
hash = (hash << 5) - hash + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
/** Derived from https://stackoverflow.com/a/32922084 */
export function deepEquals(x: any, y: any): boolean {
const ok = Object.keys,
tx = typeof x,
ty = typeof y;
const res =
x && y && tx === ty && tx === "object"
? ok(x).length === ok(y).length &&
ok(x).every((key) => deepEquals(x[key], y[key]))
: x === y;
return res;
}
/** Get tailwind text color class from type name */
export function getTypeTextColor(type: string | null): string {
if (type === null) return "text-gray-500";
return (
{
string: "text-green-500",
number: "text-blue-500",
boolean: "text-yellow-500",
object: "text-purple-500",
array: "text-indigo-500",
null: "text-gray-500",
any: "text-gray-500",
"": "text-gray-500",
}[type] || "text-gray-500"
);
}
/** Get tailwind bg color class from type name */
export function getTypeBgColor(type: string | null): string {
if (type === null) return "border-gray-500";
return (
{
string: "border-green-500",
number: "border-blue-500",
boolean: "border-yellow-500",
object: "border-purple-500",
array: "border-indigo-500",
null: "border-gray-500",
any: "border-gray-500",
"": "border-gray-500",
}[type] || "border-gray-500"
);
}
export function getTypeColor(type: string | null): string {
if (type === null) return "#6b7280";
return (
{
string: "#22c55e",
number: "#3b82f6",
boolean: "#eab308",
object: "#a855f7",
array: "#6366f1",
null: "#6b7280",
any: "#6b7280",
"": "#6b7280",
}[type] || "#6b7280"
);
}
export function beautifyString(name: string): string {
// Regular expression to identify places to split, considering acronyms
const result = name
.replace(/([a-z])([A-Z])/g, "$1 $2") // Add space before capital letters
.replace(/([A-Z])([A-Z][a-z])/g, "$1 $2") // Add space between acronyms and next word
.replace(/_/g, " ") // Replace underscores with spaces
.replace(/\b\w/g, (char) => char.toUpperCase()); // Capitalize the first letter of each word
return applyExceptions(result);
}
const exceptionMap: Record<string, string> = {
"Auto GPT": "AutoGPT",
Gpt: "GPT",
Creds: "Credentials",
Id: "ID",
Openai: "OpenAI",
Api: "API",
Url: "URL",
Http: "HTTP",
Json: "JSON",
};
const applyExceptions = (str: string): string => {
Object.keys(exceptionMap).forEach((key) => {
const regex = new RegExp(`\\b${key}\\b`, "g");
str = str.replace(regex, exceptionMap[key]);
});
return str;
};
export function exportAsJSONFile(obj: object, filename: string): void {
// Create downloadable blob
const jsonString = JSON.stringify(obj, null, 2);
const blob = new Blob([jsonString], { type: "application/json" });
const url = URL.createObjectURL(blob);
// Trigger the browser to download the blob to a file
const link = document.createElement("a");
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// Clean up
URL.revokeObjectURL(url);
}
export function setNestedProperty(obj: any, path: string, value: any) {
const keys = path.split(/[\/.]/); // Split by / or .
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (!current[key] || typeof current[key] !== "object") {
current[key] = {};
}
current = current[key];
}
current[keys[keys.length - 1]] = value;
}
export function removeEmptyStringsAndNulls(obj: any): any {
if (Array.isArray(obj)) {
// If obj is an array, recursively check each element,
// but element removal is avoided to prevent index changes.
return obj.map((item) =>
item === undefined || item === null
? ""
: removeEmptyStringsAndNulls(item),
);
} else if (typeof obj === "object" && obj !== null) {
// If obj is an object, recursively remove empty strings and nulls from its properties
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
if (
value === null ||
value === undefined ||
(typeof value === "string" && value === "")
) {
delete obj[key];
} else {
obj[key] = removeEmptyStringsAndNulls(value);
}
}
}
}
return obj;
}
export const categoryColorMap: Record<string, string> = {
AI: "bg-orange-300",
SOCIAL: "bg-yellow-300",
TEXT: "bg-green-300",
SEARCH: "bg-blue-300",
BASIC: "bg-purple-300",
INPUT: "bg-cyan-300",
OUTPUT: "bg-red-300",
LOGIC: "bg-teal-300",
DEVELOPER_TOOLS: "bg-fuchsia-300",
};
export function getPrimaryCategoryColor(categories: Category[]): string {
if (categories.length === 0) {
return "bg-gray-300";
}
return categoryColorMap[categories[0].category] || "bg-gray-300";
}
export function filterBlocksByType<T>(
blocks: T[],
predicate: (block: T) => boolean,
): T[] {
return blocks.filter(predicate);
}
export enum BehaveAs {
CLOUD = "CLOUD",
LOCAL = "LOCAL",
}
export function getBehaveAs(): BehaveAs {
return process.env.NEXT_PUBLIC_BEHAVE_AS === "CLOUD"
? BehaveAs.CLOUD
: BehaveAs.LOCAL;
}