mirror of
https://github.com/hex248/sprint.git
synced 2026-02-07 18:23:03 +00:00
added *_MAX_LENGTH variables project wide
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { ORG_DESCRIPTION_MAX_LENGTH, ORG_NAME_MAX_LENGTH, ORG_SLUG_MAX_LENGTH } from "@issue/shared";
|
||||||
import { type FormEvent, useState } from "react";
|
import { type FormEvent, useState } from "react";
|
||||||
import { useAuthenticatedSession } from "@/components/session-provider";
|
import { useAuthenticatedSession } from "@/components/session-provider";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -62,8 +63,9 @@ export function CreateOrganisation({
|
|||||||
setError(null);
|
setError(null);
|
||||||
setSubmitAttempted(true);
|
setSubmitAttempted(true);
|
||||||
|
|
||||||
if (name.trim() === "" || name.trim().length > 16) return;
|
if (name.trim() === "" || name.trim().length > ORG_NAME_MAX_LENGTH) return;
|
||||||
if (slug.trim() === "" || slug.trim().length > 16) return;
|
if (slug.trim() === "" || slug.trim().length > ORG_SLUG_MAX_LENGTH) return;
|
||||||
|
if (description.trim().length > ORG_DESCRIPTION_MAX_LENGTH) return;
|
||||||
|
|
||||||
if (!user.id) {
|
if (!user.id) {
|
||||||
setError("you must be logged in to create an organisation");
|
setError("you must be logged in to create an organisation");
|
||||||
@@ -104,7 +106,7 @@ export function CreateOrganisation({
|
|||||||
{trigger || <Button variant="outline">Create Organisation</Button>}
|
{trigger || <Button variant="outline">Create Organisation</Button>}
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
|
||||||
<DialogContent className={cn("w-md", error && "border-destructive")}>
|
<DialogContent className={cn("w-md", error ? "border-destructive" : "")}>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Create Organisation</DialogTitle>
|
<DialogTitle>Create Organisation</DialogTitle>
|
||||||
{/* <DialogDescription>Enter the details for the new organisation.</DialogDescription> */}
|
{/* <DialogDescription>Enter the details for the new organisation.</DialogDescription> */}
|
||||||
@@ -122,15 +124,16 @@ export function CreateOrganisation({
|
|||||||
setSlug(slugify(nextName));
|
setSlug(slugify(nextName));
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
validate={(v) =>
|
validate={(v) => {
|
||||||
v.trim() === ""
|
if (v.trim() === "") return "Cannot be empty";
|
||||||
? "Cannot be empty"
|
if (v.trim().length > ORG_NAME_MAX_LENGTH) {
|
||||||
: v.trim().length > 16
|
return `Too long (${ORG_NAME_MAX_LENGTH} character limit)`;
|
||||||
? "Too long (16 character limit)"
|
}
|
||||||
: undefined
|
return undefined;
|
||||||
}
|
}}
|
||||||
submitAttempted={submitAttempted}
|
submitAttempted={submitAttempted}
|
||||||
placeholder="Demo Organisation"
|
placeholder="Demo Organisation"
|
||||||
|
maxLength={ORG_NAME_MAX_LENGTH}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
label="Slug"
|
label="Slug"
|
||||||
@@ -139,25 +142,30 @@ export function CreateOrganisation({
|
|||||||
setSlug(slugify(e.target.value));
|
setSlug(slugify(e.target.value));
|
||||||
setSlugManuallyEdited(true);
|
setSlugManuallyEdited(true);
|
||||||
}}
|
}}
|
||||||
validate={(v) =>
|
validate={(v) => {
|
||||||
v.trim() === ""
|
if (v.trim() === "") return "Cannot be empty";
|
||||||
? "Cannot be empty"
|
if (v.trim().length > ORG_SLUG_MAX_LENGTH) {
|
||||||
: v.trim().length > 16
|
return `Too long (${ORG_SLUG_MAX_LENGTH} character limit)`;
|
||||||
? "Too long (16 character limit)"
|
}
|
||||||
: undefined
|
return undefined;
|
||||||
}
|
}}
|
||||||
submitAttempted={submitAttempted}
|
submitAttempted={submitAttempted}
|
||||||
placeholder="demo-organisation"
|
placeholder="demo-organisation"
|
||||||
|
maxLength={ORG_SLUG_MAX_LENGTH}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
label="Description (optional)"
|
label="Description (optional)"
|
||||||
value={description}
|
value={description}
|
||||||
onChange={(e) => setDescription(e.target.value)}
|
onChange={(e) => setDescription(e.target.value)}
|
||||||
validate={(v) =>
|
validate={(v) => {
|
||||||
v.trim().length > 2048 ? "Too long (2048 character limit)" : undefined
|
if (v.trim().length > ORG_DESCRIPTION_MAX_LENGTH) {
|
||||||
}
|
return `Too long (${ORG_DESCRIPTION_MAX_LENGTH} character limit)`;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}}
|
||||||
submitAttempted={submitAttempted}
|
submitAttempted={submitAttempted}
|
||||||
placeholder="What is this organisation for?"
|
placeholder="What is this organisation for?"
|
||||||
|
maxLength={ORG_DESCRIPTION_MAX_LENGTH}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex items-end justify-end w-full text-xs -mb-2 -mt-2">
|
<div className="flex items-end justify-end w-full text-xs -mb-2 -mt-2">
|
||||||
@@ -179,9 +187,10 @@ export function CreateOrganisation({
|
|||||||
disabled={
|
disabled={
|
||||||
submitting ||
|
submitting ||
|
||||||
name.trim() === "" ||
|
name.trim() === "" ||
|
||||||
name.trim().length > 16 ||
|
name.trim().length > ORG_NAME_MAX_LENGTH ||
|
||||||
slug.trim() === "" ||
|
slug.trim() === "" ||
|
||||||
slug.trim().length > 16
|
slug.trim().length > ORG_SLUG_MAX_LENGTH ||
|
||||||
|
description.trim().length > ORG_DESCRIPTION_MAX_LENGTH
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{submitting ? "Creating..." : "Create"}
|
{submitting ? "Creating..." : "Create"}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ProjectRecord } from "@issue/shared";
|
import { PROJECT_NAME_MAX_LENGTH, type ProjectRecord } from "@issue/shared";
|
||||||
import { type FormEvent, useState } from "react";
|
import { type FormEvent, useState } from "react";
|
||||||
import { useAuthenticatedSession } from "@/components/session-provider";
|
import { useAuthenticatedSession } from "@/components/session-provider";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -61,7 +61,12 @@ export function CreateProject({
|
|||||||
setError(null);
|
setError(null);
|
||||||
setSubmitAttempted(true);
|
setSubmitAttempted(true);
|
||||||
|
|
||||||
if (name.trim() === "" || key.trim() === "" || key.length > 4) {
|
if (
|
||||||
|
name.trim() === "" ||
|
||||||
|
name.trim().length > PROJECT_NAME_MAX_LENGTH ||
|
||||||
|
key.trim() === "" ||
|
||||||
|
key.length > 4
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +120,7 @@ export function CreateProject({
|
|||||||
)}
|
)}
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
|
||||||
<DialogContent className={cn("w-md", error && "border-destructive")}>
|
<DialogContent className={cn("w-md", error ? "border-destructive" : "")}>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Create Project</DialogTitle>
|
<DialogTitle>Create Project</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
@@ -132,9 +137,16 @@ export function CreateProject({
|
|||||||
setKey(keyify(nextName));
|
setKey(keyify(nextName));
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
validate={(v) => (v.trim() === "" ? "Cannot be empty" : undefined)}
|
validate={(v) => {
|
||||||
|
if (v.trim() === "") return "Cannot be empty";
|
||||||
|
if (v.trim().length > PROJECT_NAME_MAX_LENGTH) {
|
||||||
|
return `Too long (${PROJECT_NAME_MAX_LENGTH} character limit)`;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}}
|
||||||
submitAttempted={submitAttempted}
|
submitAttempted={submitAttempted}
|
||||||
placeholder="Demo Project"
|
placeholder="Demo Project"
|
||||||
|
maxLength={PROJECT_NAME_MAX_LENGTH}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
label="Key"
|
label="Key"
|
||||||
@@ -171,6 +183,7 @@ export function CreateProject({
|
|||||||
disabled={
|
disabled={
|
||||||
submitting ||
|
submitting ||
|
||||||
(name.trim() === "" && submitAttempted) ||
|
(name.trim() === "" && submitAttempted) ||
|
||||||
|
(name.trim().length > PROJECT_NAME_MAX_LENGTH && submitAttempted) ||
|
||||||
((key.trim() === "" || key.length > 4) && submitAttempted)
|
((key.trim() === "" || key.length > 4) && submitAttempted)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -42,6 +42,16 @@ export {
|
|||||||
UserSelectSchema,
|
UserSelectSchema,
|
||||||
} from "./schema";
|
} from "./schema";
|
||||||
|
|
||||||
|
export const ORG_NAME_MAX_LENGTH = 256;
|
||||||
|
export const ORG_DESCRIPTION_MAX_LENGTH = 1024;
|
||||||
|
export const ORG_SLUG_MAX_LENGTH = 64;
|
||||||
|
|
||||||
|
export const PROJECT_NAME_MAX_LENGTH = 256;
|
||||||
|
export const PROJECT_DESCRIPTION_MAX_LENGTH = 1024;
|
||||||
|
export const PROJECT_SLUG_MAX_LENGTH = 64;
|
||||||
|
|
||||||
|
export const ISSUE_TITLE_MAX_LENGTH = 256;
|
||||||
|
export const ISSUE_DESCRIPTION_MAX_LENGTH = 2048;
|
||||||
export const ISSUE_STATUS_MAX_LENGTH = 24;
|
export const ISSUE_STATUS_MAX_LENGTH = 24;
|
||||||
|
|
||||||
export { calculateBreakTimeMs, calculateWorkTimeMs, isTimerRunning } from "./utils/time-tracking";
|
export { calculateBreakTimeMs, calculateWorkTimeMs, isTimerRunning } from "./utils/time-tracking";
|
||||||
|
|||||||
@@ -1,6 +1,17 @@
|
|||||||
import { integer, pgTable, timestamp, uniqueIndex, varchar } from "drizzle-orm/pg-core";
|
import { integer, pgTable, timestamp, uniqueIndex, varchar } from "drizzle-orm/pg-core";
|
||||||
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
|
import {
|
||||||
|
ISSUE_DESCRIPTION_MAX_LENGTH,
|
||||||
|
ISSUE_STATUS_MAX_LENGTH,
|
||||||
|
ISSUE_TITLE_MAX_LENGTH,
|
||||||
|
ORG_DESCRIPTION_MAX_LENGTH,
|
||||||
|
ORG_NAME_MAX_LENGTH,
|
||||||
|
ORG_SLUG_MAX_LENGTH,
|
||||||
|
PROJECT_DESCRIPTION_MAX_LENGTH,
|
||||||
|
PROJECT_NAME_MAX_LENGTH,
|
||||||
|
PROJECT_SLUG_MAX_LENGTH,
|
||||||
|
} from "./index";
|
||||||
|
|
||||||
export const User = pgTable("User", {
|
export const User = pgTable("User", {
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
@@ -14,10 +25,13 @@ export const User = pgTable("User", {
|
|||||||
|
|
||||||
export const Organisation = pgTable("Organisation", {
|
export const Organisation = pgTable("Organisation", {
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
name: varchar({ length: 256 }).notNull(),
|
name: varchar({ length: ORG_NAME_MAX_LENGTH }).notNull(),
|
||||||
description: varchar({ length: 1024 }),
|
description: varchar({ length: ORG_DESCRIPTION_MAX_LENGTH }),
|
||||||
slug: varchar({ length: 64 }).notNull().unique(),
|
slug: varchar({ length: ORG_SLUG_MAX_LENGTH }).notNull().unique(),
|
||||||
statuses: varchar({ length: 64 }).array().notNull().default(["TO DO", "IN PROGRESS", "REVIEW", "DONE"]),
|
statuses: varchar({ length: ISSUE_STATUS_MAX_LENGTH })
|
||||||
|
.array()
|
||||||
|
.notNull()
|
||||||
|
.default(["TO DO", "IN PROGRESS", "REVIEW", "DONE", "ARCHIVED", "MERGED"]),
|
||||||
createdAt: timestamp({ withTimezone: false }).defaultNow(),
|
createdAt: timestamp({ withTimezone: false }).defaultNow(),
|
||||||
updatedAt: timestamp({ withTimezone: false }).defaultNow(),
|
updatedAt: timestamp({ withTimezone: false }).defaultNow(),
|
||||||
});
|
});
|
||||||
@@ -37,7 +51,9 @@ export const OrganisationMember = pgTable("OrganisationMember", {
|
|||||||
export const Project = pgTable("Project", {
|
export const Project = pgTable("Project", {
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
key: varchar({ length: 4 }).notNull(),
|
key: varchar({ length: 4 }).notNull(),
|
||||||
name: varchar({ length: 256 }).notNull(),
|
name: varchar({ length: PROJECT_NAME_MAX_LENGTH }).notNull(),
|
||||||
|
description: varchar({ length: PROJECT_DESCRIPTION_MAX_LENGTH }),
|
||||||
|
slug: varchar({ length: PROJECT_SLUG_MAX_LENGTH }).notNull().unique(),
|
||||||
organisationId: integer()
|
organisationId: integer()
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => Organisation.id),
|
.references(() => Organisation.id),
|
||||||
@@ -79,9 +95,9 @@ export const Issue = pgTable(
|
|||||||
|
|
||||||
number: integer("number").notNull(),
|
number: integer("number").notNull(),
|
||||||
|
|
||||||
title: varchar({ length: 256 }).notNull(),
|
title: varchar({ length: ISSUE_TITLE_MAX_LENGTH }).notNull(),
|
||||||
description: varchar({ length: 2048 }).notNull(),
|
description: varchar({ length: ISSUE_DESCRIPTION_MAX_LENGTH }).notNull(),
|
||||||
status: varchar({ length: 64 }).notNull().default("TO DO"),
|
status: varchar({ length: ISSUE_STATUS_MAX_LENGTH }).notNull().default("TO DO"),
|
||||||
|
|
||||||
creatorId: integer()
|
creatorId: integer()
|
||||||
.notNull()
|
.notNull()
|
||||||
|
|||||||
Reference in New Issue
Block a user