Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c07bc33
db change and new workspace slug
MichaelUnkey Aug 25, 2025
0560ccc
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
MichaelUnkey Aug 25, 2025
b255d98
rabbits
MichaelUnkey Aug 26, 2025
f4eb278
small changes
MichaelUnkey Aug 26, 2025
506e25a
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
MichaelUnkey Aug 26, 2025
c676bce
remove journal
MichaelUnkey Aug 26, 2025
bb7900d
rabbit
MichaelUnkey Aug 26, 2025
f6b2383
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
MichaelUnkey Aug 26, 2025
1b4f0c5
workspaceUrl changed to slug and regex changed.
MichaelUnkey Aug 28, 2025
2984797
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
MichaelUnkey Aug 28, 2025
60dc06e
rabbit comment missed name in descriptions and narrowed regex
MichaelUnkey Aug 28, 2025
c87e538
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
MichaelUnkey Aug 28, 2025
f1191b8
Update apps/dashboard/app/new/hooks/use-workspace-step.tsx
MichaelUnkey Aug 28, 2025
b87eba9
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
MichaelUnkey Aug 28, 2025
64122d8
safari rabbit fix
MichaelUnkey Aug 28, 2025
2170a12
rabbit nit
MichaelUnkey Aug 29, 2025
14a6e61
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
MichaelUnkey Aug 29, 2025
6cf2e6d
Merge branch 'main' of https://github.com/unkeyed/unkey into workspac…
chronark Aug 31, 2025
af74624
fix: shema
chronark Aug 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/api/src/pkg/testutil/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ export abstract class Harness {
const unkeyWorkspace: Workspace = {
id: newId("test"),
name: "unkey",
slug: "unkey-workspace",
orgId: newId("test"),
plan: "enterprise",
tier: "Enterprise",
Expand All @@ -272,6 +273,7 @@ export abstract class Harness {
const userWorkspace: Workspace = {
id: newId("test"),
name: "user",
slug: "user-workspace",
orgId: newId("test"),
plan: "pro",
tier: "Pro Max",
Expand Down
74 changes: 37 additions & 37 deletions apps/dashboard/app/new/hooks/use-workspace-step.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ const workspaceSchema = z.object({
.trim()
.min(3, "Workspace name is required")
.max(50, "Workspace name must be 50 characters or less"),
// workspaceUrl: z
// .string()
// .min(3, "Workspace URL is required")
// .regex(
// /^[a-zA-Z0-9-_]+$/,
// "URL handle can only contain letters, numbers, hyphens, and underscores"
// ),
workspaceUrl: z
Comment thread
MichaelUnkey marked this conversation as resolved.
Outdated
.string()
.min(3, "Workspace URL is required")
.regex(
/^[a-zA-Z0-9-_]+$/,
"URL handle can only contain letters, numbers, hyphens, and underscores",
),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
MichaelUnkey marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

type WorkspaceFormData = z.infer<typeof workspaceSchema>;

export const useWorkspaceStep = (): OnboardingStep => {
// const [isSlugGenerated, setIsSlugGenerated] = useState(false);
const [isSlugGenerated, setIsSlugGenerated] = useState(false);
const [workspaceCreated, setWorkspaceCreated] = useState(false);
const formRef = useRef<HTMLFormElement>(null);
const router = useRouter();
Expand Down Expand Up @@ -101,7 +101,10 @@ export const useWorkspaceStep = (): OnboardingStep => {
// Workspace already created, just proceed
return;
}
createWorkspace.mutateAsync({ name: data.workspaceName });
createWorkspace.mutateAsync({
name: data.workspaceName,
slug: data.workspaceUrl,
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
};

const validFieldCount = Object.keys(form.getValues()).filter((field) => {
Expand Down Expand Up @@ -151,35 +154,32 @@ export const useWorkspaceStep = (): OnboardingStep => {
{...form.register("workspaceName")}
placeholder="Enter workspace name"
label="Workspace name"
// onBlur={(evt) => {
// if (!isSlugGenerated) {
// form.setValue(
// "workspaceUrl",
// slugify(evt.currentTarget.value)
// );
// form.trigger("workspaceUrl");
// setIsSlugGenerated(true);
// }
// }}
onBlur={(evt) => {
if (!isSlugGenerated) {
form.setValue("workspaceUrl", slugify(evt.currentTarget.value));
form.trigger("workspaceUrl");
setIsSlugGenerated(true);
}
}}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
MichaelUnkey marked this conversation as resolved.
required
error={form.formState.errors.workspaceName?.message}
disabled={isLoading || workspaceCreated}
/>
{/* <FormInput */}
{/* {...form.register("workspaceUrl")} */}
{/* placeholder="enter-a-handle" */}
{/* label="Workspace URL handle" */}
{/* required */}
{/* error={form.formState.errors.workspaceUrl?.message} */}
{/* prefix="app.unkey.com/" */}
{/* /> */}
<FormInput
{...form.register("workspaceUrl")}
placeholder="enter-a-handle"
label="Workspace URL handle"
required
error={form.formState.errors.workspaceUrl?.message}
prefix="app.unkey.com/"
/>
Comment thread
MichaelUnkey marked this conversation as resolved.
</div>
</div>
</form>
),
kind: "required" as const,
validFieldCount,
requiredFieldCount: 1,
requiredFieldCount: 2,
buttonText: workspaceCreated ? "Continue" : "Create workspace",
description: workspaceCreated
? "Workspace created successfully, continue to next step"
Expand All @@ -200,12 +200,12 @@ export const useWorkspaceStep = (): OnboardingStep => {
};
};

// const slugify = (text: string): string => {
// return text
// .toLowerCase()
// .trim()
// .replace(/[^\w\s-]/g, "") // Remove special chars except spaces and hyphens
// .replace(/\s+/g, "-") // Replace spaces with hyphens
// .replace(/-+/g, "-") // Replace multiple hyphens with single
// .replace(/^-|-$/g, ""); // Remove leading/trailing hyphens
// };
const slugify = (text: string): string => {
return text
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "") // Remove special chars except spaces and hyphens
.replace(/\s+/g, "-") // Replace spaces with hyphens
.replace(/-+/g, "-") // Replace multiple hyphens with single
.replace(/^-|-$/g, ""); // Remove leading/trailing hyphens
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
8 changes: 7 additions & 1 deletion apps/dashboard/lib/trpc/routers/workspace/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ export const createWorkspace = t.procedure
.use(requireUser)
.input(
z.object({
name: z.string().min(1).max(50),
name: z.string().min(3).max(50),
slug: z
.string()
.min(3)
.max(64)
.regex(/^[a-zA-Z0-9-_]+$/),
}),
Comment thread
MichaelUnkey marked this conversation as resolved.
)
.mutation(async ({ ctx, input }) => {
Expand Down Expand Up @@ -50,6 +55,7 @@ export const createWorkspace = t.procedure
id: newId("workspace"),
orgId: orgId,
name: input.name,
slug: input.slug,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
plan: "free",
tier: "Free",
stripeCustomerId: null,
Expand Down
3 changes: 3 additions & 0 deletions internal/db/drizzle/0001_legal_kat_farrell.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE `permissions` DROP INDEX `unique_name_per_workspace_idx`;--> statement-breakpoint
ALTER TABLE `workspaces` ADD CONSTRAINT `workspaces_slug_unique` UNIQUE(`slug`);--> statement-breakpoint
ALTER TABLE `workspaces` ADD `slug` varchar(256);
Comment thread
MichaelUnkey marked this conversation as resolved.
Outdated
Loading
Loading