Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/helpers/PropertyHelper.ts
T

233 lines
8.9 KiB
TypeScript

import { Property } from "@toolctrl/db/prisma-browser";
import { TFunction } from "i18next";
import { MediaDto } from "~/application/dtos/entities/MediaDto";
import { PropertyAttributeName } from "~/application/enums/entities/PropertyAttributeName";
import { PropertyType } from "~/application/enums/entities/PropertyType";
import { TemplateEntityPropertyTypeDto } from "~/modules/templates/EntityTemplateDto";
import { EntityWithProperties, PropertyWithDetails } from "../db/entities/entities.db.server";
import PropertyAttributeHelper from "./PropertyAttributeHelper";
import { RowValueMultipleDto } from "~/application/dtos/entities/RowValueMultipleDto";
export const validateProperty = async (name: string, title: string, properties: Property[], property?: Property | null, t?: TFunction) => {
const errors: string[] = [];
if (!property || property?.name !== name) {
const existingName = properties.find((f) => f.name === name);
if (existingName) {
errors.push(
t
? t("models.property.errors.existingName", { name, title: existingName.title })
: `Existing property with name '${name}': ${existingName.title}`
);
}
}
if (!property || property?.title !== title) {
const existingTitle = properties.find((f) => f.title === title);
if (existingTitle) {
errors.push(
t
? t("models.property.errors.existingTitle", { title, existingTitle: existingTitle.title })
: `Existing entity with title '${title}': ${existingTitle.title}`
);
}
}
return errors;
};
export const defaultProperties: {
order: number;
name: string;
title: string;
type: number;
// formula?: string | null;
parentId?: string | null;
isDefault: boolean;
isRequired: boolean;
isHidden: boolean;
isDisplay: boolean;
}[] = [
{
name: "id",
title: "ID",
order: 1,
type: PropertyType.NUMBER,
// options: [],
isDefault: true,
isRequired: false,
isHidden: true,
// formula: undefined,
isDisplay: false,
},
{
name: "folio",
title: "models.row.folio",
order: 2,
type: PropertyType.NUMBER,
// options: [],
isDefault: true,
isRequired: false,
isHidden: true,
// formula: undefined,
isDisplay: false,
},
{
name: "createdAt",
title: "shared.createdAt",
order: 3,
type: PropertyType.DATE,
// options: [],
isDefault: true,
isRequired: false,
isHidden: true,
// formula: undefined,
isDisplay: false,
},
];
export function validatePropertyValue({ t, property, value }: { t?: TFunction; property: PropertyWithDetails; value: any }) {
const max = PropertyAttributeHelper.getPropertyAttributeValue_Number(property, PropertyAttributeName.Max);
const min = PropertyAttributeHelper.getPropertyAttributeValue_Number(property, PropertyAttributeName.Min);
if (max) {
if (property.type === PropertyType.TEXT) {
if (value.length > max) {
throwError({ t, property, error: `must have less than ${max} characters (${value})` });
}
} else if (property.type === PropertyType.NUMBER) {
if (!!value && Number(value) > max) {
throwError({ t, property, error: `must be less than ${max} (${value})` });
}
}
}
if (min) {
if (property.type === PropertyType.TEXT) {
if (value.length < min) {
throwError({ t, property, error: `must have less than ${min} characters (${value})` });
}
} else if (property.type === PropertyType.NUMBER) {
if (!!value && Number(value) < min) {
throwError({ t, property, error: `must be greater than ${min} (${value})` });
}
}
}
return true;
}
function throwError({ t, property, error }: { t?: TFunction; property: Property; error: string }) {
if (t) {
throw Error(`${t(property.title)}: ${error}`);
}
throw Error(`${property.name}: ${error}`);
}
export function validatePropertyValue_Media({ t, property, media }: { t?: TFunction; property: PropertyWithDetails; media: MediaDto[] }) {
const max = PropertyAttributeHelper.getPropertyAttributeValue_Number(property, PropertyAttributeName.Max);
const min = PropertyAttributeHelper.getPropertyAttributeValue_Number(property, PropertyAttributeName.Min);
if (property.isRequired && media.length === 0) {
throwError({ t, property, error: `required` });
} else if (max && media.length > max) {
if (max === 1) {
throwError({ t, property, error: `can only have one file` });
} else {
throwError({ t, property, error: `cannot have more than ${max} files` });
}
} else if (min && media.length < min) {
if (min === 1) {
throwError({ t, property, error: `must have at least one file` });
} else {
throwError({ t, property, error: `must have at least ${min} files` });
}
}
return true;
}
export function validatePropertyValue_Multiple({ t, property, multiple }: { t?: TFunction; property: PropertyWithDetails; multiple: RowValueMultipleDto[] }) {
const max = PropertyAttributeHelper.getPropertyAttributeValue_Number(property, PropertyAttributeName.Max);
const min = PropertyAttributeHelper.getPropertyAttributeValue_Number(property, PropertyAttributeName.Min);
if (property.isRequired && multiple.length === 0) {
throwError({ t, property, error: `required` });
} else if (max && multiple.length > max) {
if (max === 1) {
throwError({ t, property, error: `can only have one` });
} else {
throwError({ t, property, error: `cannot have more than ${max}` });
}
} else if (min && multiple.length < min) {
if (min === 1) {
throwError({ t, property, error: `must have at least one` });
} else {
throwError({ t, property, error: `must have at least ${min}` });
}
}
return true;
}
export function mapToEntityTemplateType(type: PropertyType): TemplateEntityPropertyTypeDto {
switch (type) {
case PropertyType.NUMBER:
return "number";
case PropertyType.TEXT:
return "string";
case PropertyType.DATE:
return "date";
case PropertyType.MEDIA:
return "media";
case PropertyType.SELECT:
return "select";
case PropertyType.BOOLEAN:
return "boolean";
case PropertyType.MULTI_SELECT:
return "multiSelect";
case PropertyType.MULTI_TEXT:
return "multiText";
case PropertyType.RANGE_NUMBER:
return "rangeNumber";
case PropertyType.RANGE_DATE:
return "rangeDate";
case PropertyType.FORMULA:
return "formula";
default:
return "string";
}
}
export enum RowDisplayDefaultProperty {
ID = "default.id",
ENTITY = "default.entity",
TENANT = "default.tenant",
ORDER = "default.order",
FOLIO = "default.folio",
CREATED_AT = "default.createdAt",
CREATED_BY = "default.createdBy",
PERMISSIONS = "default.permissions",
TAGS = "default.tags",
TASKS = "default.tasks",
COMMENTS = "default.comments",
HIDDEN_PARENTS = "default.hiddenParents",
HIDDEN_CHILDREN = "default.hiddenChildren",
}
export const defaultDisplayProperties: { name: string; title: string; position: "before" | "after"; displayedByDefault: boolean }[] = [
{ name: RowDisplayDefaultProperty.ID, title: "ID", position: "before", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.ENTITY, title: "models.row.entity", position: "before", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.TENANT, title: "models.row.tenant", position: "before", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.ORDER, title: "models.row.order", position: "before", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.FOLIO, title: "models.row.folio", position: "before", displayedByDefault: true },
{ name: RowDisplayDefaultProperty.CREATED_AT, title: "models.row.createdAt", position: "after", displayedByDefault: true },
{ name: RowDisplayDefaultProperty.CREATED_BY, title: "models.row.createdBy", position: "after", displayedByDefault: true },
{ name: RowDisplayDefaultProperty.PERMISSIONS, title: "models.row.permissions", position: "after", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.TAGS, title: "models.row.tags", position: "after", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.TASKS, title: "models.row.tasks", position: "after", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.COMMENTS, title: "models.row.comments", position: "after", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.HIDDEN_PARENTS, title: "", position: "after", displayedByDefault: false },
{ name: RowDisplayDefaultProperty.HIDDEN_CHILDREN, title: "", position: "after", displayedByDefault: false },
];
export function getFormProperties({ mode, entity, properties }: { mode: "create" | "edit"; entity: EntityWithProperties; properties?: string[] }) {
let items = entity.properties.filter((f) => !f.isDefault && !f.isHidden && (properties === undefined || properties.includes(f.name)));
if (mode === "create") {
items = items.filter((f) => f.showInCreate);
}
return items;
}