From f2a193ac8da71b7f1ba1685086b3465ce3c6cf73 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:06:57 +0100 Subject: [PATCH] Allow creation of space * other fixes and cleanups --- apps/client/index.html | 3 +- apps/client/public/favicon-16x16.png | Bin 0 -> 562 bytes apps/client/public/favicon-32x32.png | Bin 0 -> 1064 bytes .../src/components/common/recent-changes.tsx | 2 +- .../components/layouts/global/top-menu.tsx | 7 +- .../features/auth/components/login-form.tsx | 5 - .../space/components/create-space-form.tsx | 110 ++++++++++++++++++ .../space/components/create-space-modal.tsx | 18 +++ .../space/components/edit-space-form.tsx | 10 ++ .../components/sidebar/space-sidebar.tsx | 20 +++- .../src/features/space/queries/space-query.ts | 31 +++-- .../features/space/services/space-service.ts | 5 + .../user/components/account-avatar.tsx | 2 - .../components/workspace-name-form.tsx | 1 + .../workspace/queries/workspace-query.ts | 2 +- apps/client/src/lib/utils.ts | 14 ++- .../src/pages/settings/space/spaces.tsx | 10 ++ .../src/collaboration/collaboration.util.ts | 4 +- .../src/core/space/dto/create-space.dto.ts | 4 +- .../src/core/space/services/space.service.ts | 48 +++++++- .../server/src/core/space/space.controller.ts | 23 ++++ .../src/database/repos/space/space.repo.ts | 2 +- 22 files changed, 289 insertions(+), 32 deletions(-) create mode 100644 apps/client/public/favicon-16x16.png create mode 100644 apps/client/public/favicon-32x32.png create mode 100644 apps/client/src/features/space/components/create-space-form.tsx create mode 100644 apps/client/src/features/space/components/create-space-modal.tsx diff --git a/apps/client/index.html b/apps/client/index.html index e4528b7c..98e02c8b 100644 --- a/apps/client/index.html +++ b/apps/client/index.html @@ -2,7 +2,8 @@ - + + Docmost diff --git a/apps/client/public/favicon-16x16.png b/apps/client/public/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..6298fe8a9ab3a722257a19179ca368f761d97374 GIT binary patch literal 562 zcmV-20?qx2P)Px$>`6pHR5(v6|n7iom%+&cJwxfH9PpfEX|W=(>CA9oQP- zLf>CNJi*v4`6m0+V!d*vtuG-4wmCZ6pRo&=tItbRpenSyjGqDAS9ln5H5grd(t#TWRFI(LGPqTtzM%Qws@L9?R0mcK(Vdx zh@0;>Mf++{i#X=??v~3hm#o(7qH&7p5W(!s&#P&09jhsqi?#={xl-%;|3wh*HAR$a zZMkD`1=-6^>*+8F=NQg(B3-oqAK!l&vPHP~3sigV1?f|%AOHXW07*qoM6N<$f}Pq9 AW&i*H literal 0 HcmV?d00001 diff --git a/apps/client/public/favicon-32x32.png b/apps/client/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..40d6a30e9cbdf66d344942fb9ba0d8378e6a92c6 GIT binary patch literal 1064 zcmV+@1lRkCP)Px&;z>k7R9HuqSHDXmK@|Qbm4ASsR^kQmVj)}tf*@z1TuwZ&w6oG8T11OPlT$2W z0+-~<1Fy2s%2K?LLn{SEPQ^wLZ1pakVC6+{j+xmXGrKdpdt2yc_RV|WydU3tLjc4; zPz1;#p|l$SDEmX~7xqd(#VUXNzlA)PaKt19)-LgnGSL>L_y(ZDq}BkGWEshpV^V1L zDs?caFI>zotJ%HI*8TwCCy%CHFBNUC4{%G}7eR|pge?fq`W>e^k}fcAa19={BhU3Q zGgS2!Ve$8BaV#mx%%dwUyweSLg6lgVIf>$}WM+E8j8WG@N;1)*^z`sN=g}4i{bSMCQ4dML!9K*xI z+zVY@U3hwW@_?|2omn?=7~5eAL11D7C=?2)R4Ux))YK<58b8coP)JOsGy;@2tumxQ zV$e;(pb)TclarHZG#XqipUf_3L_)u0vuvy;3XGTOC4;YaXAo(td%gak{vsSBdFPNgOA!HY;ISEyu>bL@=(;v`m z{^W{QS6A`nOV#27b)T;ncvIER0ahl15)p;vKrWX(~-{03)yr=@-1m@@u zE<*K8nZHk)R*d-{j>j-eoC<+QMnvCiSw=^e?Aj*j?1BA?sP zuN-9|9tv}yy}|?xBHfMB$sgMZfbr$R2;&7$k(taUI^pH;FNH# zW=;YG*ff6 ) : ( - No records to show + No pages yet ); } diff --git a/apps/client/src/components/layouts/global/top-menu.tsx b/apps/client/src/components/layouts/global/top-menu.tsx index 07e87f12..7c82f231 100644 --- a/apps/client/src/components/layouts/global/top-menu.tsx +++ b/apps/client/src/components/layouts/global/top-menu.tsx @@ -29,10 +29,11 @@ export default function TopMenu() { - diff --git a/apps/client/src/features/auth/components/login-form.tsx b/apps/client/src/features/auth/components/login-form.tsx index 92b2c8fa..9433b1af 100644 --- a/apps/client/src/features/auth/components/login-form.tsx +++ b/apps/client/src/features/auth/components/login-form.tsx @@ -1,22 +1,17 @@ import * as React from "react"; import * as z from "zod"; - import { useForm, zodResolver } from "@mantine/form"; import useAuth from "@/features/auth/hooks/use-auth"; import { ILogin } from "@/features/auth/types/auth.types"; import { Container, Title, - Anchor, TextInput, Button, - Text, PasswordInput, Box, } from "@mantine/core"; -import { Link, useNavigate } from "react-router-dom"; import classes from "./auth.module.css"; -import { useEffect, useState } from "react"; import { useRedirectIfAuthenticated } from "@/features/auth/hooks/use-redirect-if-authenticated.ts"; const formSchema = z.object({ diff --git a/apps/client/src/features/space/components/create-space-form.tsx b/apps/client/src/features/space/components/create-space-form.tsx new file mode 100644 index 00000000..29fe46f2 --- /dev/null +++ b/apps/client/src/features/space/components/create-space-form.tsx @@ -0,0 +1,110 @@ +import { Group, Box, Button, TextInput, Stack, Textarea } from "@mantine/core"; +import React, { useEffect } from "react"; +import { useForm, zodResolver } from "@mantine/form"; +import * as z from "zod"; +import { useNavigate } from "react-router-dom"; +import { useCreateSpaceMutation } from "@/features/space/queries/space-query.ts"; +import { computeSpaceSlug } from "@/lib"; +import { getSpaceUrl } from "@/lib/config.ts"; + +const formSchema = z.object({ + name: z.string().min(2).max(50), + slug: z + .string() + .min(2) + .max(50) + .regex( + /^[a-zA-Z0-9]+$/, + "Space slug must be alphanumeric. No special characters", + ), + description: z.string().max(500), +}); +type FormValues = z.infer; + +export function CreateSpaceForm() { + const createSpaceMutation = useCreateSpaceMutation(); + const navigate = useNavigate(); + + const form = useForm({ + validate: zodResolver(formSchema), + validateInputOnChange: ["slug"], + initialValues: { + name: "", + slug: "", + description: "", + }, + }); + + useEffect(() => { + const name = form.values.name; + const words = name.trim().split(/\s+/); + + // Check if the last character is a space or if the last word is a single character (indicating it's in progress) + const lastChar = name[name.length - 1]; + const lastWordIsIncomplete = + words.length > 1 && words[words.length - 1].length === 1; + + if (lastChar !== " " || lastWordIsIncomplete) { + const slug = computeSpaceSlug(name); + form.setFieldValue("slug", slug); + } + }, [form.values.name]); + + const handleSubmit = async (data: { + name?: string; + slug?: string; + description?: string; + }) => { + const spaceData = { + name: data.name, + slug: data.slug, + description: data.description, + }; + + const createdSpace = await createSpaceMutation.mutateAsync(spaceData); + navigate(getSpaceUrl(createdSpace.slug)); + }; + + return ( + <> + +
handleSubmit(values))}> + + + + + +