Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default async function Layout({

return (
<div className="max-w-[1200px] space-y-4">
<Providers>
<Providers policyId={id}>
<main className="h-[calc(100vh-4rem-4rem)]">{children}</main>
</Providers>
</div>
Expand Down
79 changes: 52 additions & 27 deletions apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,59 @@
"use client";

import AdvancedEditor from "@/components/editor/advanced-editor";
import { DocumentSpinner } from "@/components/editor/spinner";
import { PolicyOverview } from "@/components/policies/policy-overview";
import { getI18n } from "@/locales/server";
import type { Metadata } from "next";
import { setStaticParamsLocale } from "next-international/server";
import { Room } from "./room";
import { Button } from "@bubba/ui/button";
import { Separator } from "@bubba/ui/separator";
import { ClientSideSuspense } from "@liveblocks/react";
import { useAction } from "next-safe-action/hooks";
import { useParams } from "next/navigation";
import type { JSONContent } from "novel";
import { toast } from "sonner";
import { usePolicy } from "../hooks/usePolicy";
import { publishPolicy } from "./actions/publish-policy";

interface PageProps {
params: Promise<{ locale: string; id: string }>;
}
export default function PolicyPage() {
const { id } = useParams();

const { execute, isExecuting } = useAction(
() => publishPolicy({ id: id as string }),
{
onSuccess: () => {
toast.success("Policy published successfully");
},
},
);

const { data: policy } = usePolicy({ policyId: id as string });

export default async function PolicyPage({ params }: PageProps) {
const { locale, id } = await params;
setStaticParamsLocale(locale);
if (!policy) return null;

const content = policy.content as JSONContent;

if (!content) return null;

return (
<Room>
<PolicyOverview policyId={id} />
</Room>
<div className="h-[calc(100vh-8rem)] flex flex-col py-4 gap-4">
<div className="flex justify-end">
<Button
variant="secondary"
className="w-fit"
onClick={() => execute({ id: id as string })}
>
{isExecuting ? "Publishing..." : "Publish"}
</Button>
</div>
<Separator />
<div className="flex-1">
<div className="min-h-0 h-auto">
<div className="relative min-h-[calc(100vh-250px)] w-full mx-auto border border-border bg-background">
<ClientSideSuspense fallback={<DocumentSpinner />}>
<AdvancedEditor />
</ClientSideSuspense>
</div>
</div>
</div>
</div>
);
}

export async function generateMetadata({
params,
}: {
params: Promise<{ locale: string; id: string }>;
}): Promise<Metadata> {
const { locale } = await params;
setStaticParamsLocale(locale);
const t = await getI18n();

return {
title: t("sub_pages.policies.editor"),
};
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
"use client";

import { LiveblocksProvider } from "@liveblocks/react";
import { LiveblocksProvider, RoomProvider } from "@liveblocks/react";
import { useSession } from "next-auth/react";
import { redirect } from "next/navigation";
import type { JSONContent } from "novel";
import type { PropsWithChildren } from "react";
import { usePolicy } from "../hooks/usePolicy";

interface ProvidersProps extends PropsWithChildren {
policyId: string;
}

export function Providers({ children, policyId }: ProvidersProps) {
const { data: session } = useSession();
const { data: policy } = usePolicy({ policyId });

if (!policyId || !session?.user?.organizationId) {
redirect("/policies");
}

const content = policy?.content as JSONContent;
const roomId = `liveblocks:policies:${session.user.organizationId}:${policyId}`;

export function Providers({ children }: PropsWithChildren) {
return (
<LiveblocksProvider
authEndpoint="/api/liveblocks"
Expand Down Expand Up @@ -33,7 +51,9 @@ export function Providers({ children }: PropsWithChildren) {
return userIds;
}}
>
{children}
<RoomProvider id={roomId} initialStorage={content}>
{children}
</RoomProvider>
</LiveblocksProvider>
);
}
19 changes: 0 additions & 19 deletions apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/room.tsx

This file was deleted.

15 changes: 11 additions & 4 deletions apps/app/src/components/editor/advanced-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,35 @@
import { Separator } from "@bubba/ui/separator";
import { useLiveblocksExtension } from "@liveblocks/react-tiptap";
import { useSyncStatus } from "@liveblocks/react/suspense";
import type { Extensions } from "@tiptap/react";
import type { Extensions, JSONContent } from "@tiptap/react";
import {
EditorCommand,
EditorCommandEmpty,
EditorCommandItem,
EditorCommandList,
EditorContent,
EditorRoot,
type JSONContent,
} from "novel";
import { ImageResizer, handleCommandNavigation } from "novel";
import { handleImageDrop, handleImagePaste } from "novel";
import { useState } from "react";
import { defaultExtensions } from "./extensions";
import GenerativeMenuSwitch from "./generative/generative-menu-switch";
import { uploadFn } from "./image-upload";
import { AddCommentSelector } from "./selectors/add-comment-selector";
import { ColorSelector } from "./selectors/color-selector";
import { LinkSelector } from "./selectors/link-selector";
import { MathSelector } from "./selectors/math-selector";
import { NodeSelector } from "./selectors/node-selector";
import { TextButtons } from "./selectors/text-buttons";
import { slashCommand, suggestionItems } from "./slash-command";
import { Threads } from "./threads";

export default function AdvancedEditor() {
const liveblocks = useLiveblocksExtension();
const liveblocks = useLiveblocksExtension({
offlineSupport_experimental: true,
});

const extensions: Extensions = [
...defaultExtensions,
slashCommand,
Expand Down Expand Up @@ -61,7 +65,7 @@ export default function AdvancedEditor() {
<EditorRoot>
<EditorContent
extensions={extensions}
className="p-12 relative min-h-[500px] w-full"
className="p-12 relative min-h-[calc(100vh-250px)] w-full"
editorProps={{
handleDOMEvents: {
keydown: (_view, event) => handleCommandNavigation(event),
Expand All @@ -81,6 +85,7 @@ export default function AdvancedEditor() {
slotAfter={<ImageResizer />}
immediatelyRender={false}
>
<Threads />
<EditorCommand className="z-50 h-auto max-h-[330px] overflow-y-auto rounded-md border border-muted bg-background px-1 py-2 shadow-md transition-all">
<EditorCommandEmpty className="px-2 text-muted-foreground">
No results
Expand Down Expand Up @@ -124,6 +129,8 @@ export default function AdvancedEditor() {
<TextButtons />
<Separator orientation="vertical" />
<ColorSelector open={openColor} onOpenChange={setOpenColor} />
<Separator orientation="vertical" />
<AddCommentSelector />
</GenerativeMenuSwitch>
</EditorContent>
</EditorRoot>
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/components/editor/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const tiptapLink = TiptapLink.configure({

const taskList = TaskList.configure({
HTMLAttributes: {
class: cx("not-prose pl-2 "),
class: cx("not-prose pl-2"),
},
});
const taskItem = TaskItem.configure({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Button } from "@bubba/ui/button";
import { cn } from "@bubba/ui/cn";
import { MessageSquarePlus, SigmaIcon } from "lucide-react";
import { MessageSquarePlus } from "lucide-react";
import { useEditor } from "novel";

export const AddCommentSelector = () => {
Expand Down
1 change: 0 additions & 1 deletion apps/app/src/components/editor/slash-command.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
} from "lucide-react";
import { createSuggestionItems } from "novel";
import { Command, renderItems } from "novel";
import { uploadFn } from "./image-upload";

export const suggestionItems = createSuggestionItems([
{
Expand Down
26 changes: 3 additions & 23 deletions apps/app/src/components/editor/threads.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import {
AnchoredThreads,
FloatingComposer,
FloatingThreads,
} from "@liveblocks/react-tiptap";
import { FloatingComposer, FloatingThreads } from "@liveblocks/react-tiptap";
import { useThreads } from "@liveblocks/react/suspense";
import { useEditor } from "novel";
import { useSyncExternalStore } from "react";
import "@bubba/ui/globals.css";
import "@bubba/ui/prosemirror";
import "@bubba/ui/text-editor";

export function Threads() {
const { editor } = useEditor();
const isMobile = useIsMobile();
const { threads } = useThreads({ query: { resolved: false } });

if (!editor) {
Expand All @@ -21,20 +13,8 @@ export function Threads() {

return (
<>
<FloatingComposer editor={editor} style={{ width: "350px" }} />
{isMobile ? (
<FloatingThreads
editor={editor}
threads={threads}
style={{ width: "350px" }}
/>
) : (
<AnchoredThreads
editor={editor}
threads={threads}
style={{ width: "350px" }}
/>
)}
<FloatingComposer editor={editor} color="light" />
<FloatingThreads editor={editor} threads={threads} color="light" />
</>
);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/components/policies/policy-overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function PolicyOverview({ policyId }: { policyId: string }) {
<div className="min-h-0 h-auto">
<div className="relative min-h-[1100px] w-full mx-auto border border-border bg-background">
<ClientSideSuspense fallback={<DocumentSpinner />}>
<AdvancedEditor />
<AdvancedEditor content={content} />
</ClientSideSuspense>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
<div className="flex min-h-svh flex-col">
<div className="min-h-svh flex flex-col">
<SiteHeader />
<main className="flex-1">{children}</main>
<main className="flex-1 overflow-y-auto">{children}</main>
<SiteFooter />
</div>
);
Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ export const metadata: Metadata = {

export default function Home() {
return (
<section>
<div className="container mx-auto px-4">
<div className="flex flex-col items-center py-16 md:py-24 text-center">
<Logo width={64} height={64} className="h-16 w-16 mb-10" />
<section className="w-full">
<div className="container mx-auto px-4 py-16 md:py-24">
<div className="flex flex-col items-center text-center space-y-6">
<Logo width={64} height={64} className="h-16 w-16" />

<h1 className="text-4xl md:text-5xl font-bold leading-tight tracking-tighter lg:leading-[1.1] max-w-[800px] mx-auto bg-gradient-to-r from-foreground to-foreground/70 bg-clip-text text-transparent">
<Balancer>Get SOC 2, ISO 27001 and GDPR certified</Balancer>
Expand Down
1 change: 0 additions & 1 deletion apps/web/src/app/components/waitlist-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export function WaitlistForm() {
<FormControl>
<Input
{...field}
autoFocus
type="email"
placeholder="Enter your work email"
className="h-12 px-4 text-base bg-background border-border/50 focus:border-primary"
Expand Down
13 changes: 1 addition & 12 deletions apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@ export const metadata: Metadata = {
},
};

export const viewport = {
width: "device-width",
initialScale: 1,
maximumScale: 1,
userScalable: false,
themeColor: [
{ media: "(prefers-color-scheme: light)" },
{ media: "(prefers-color-scheme: dark)" },
],
};

export const preferredRegion = ["auto"];

export default function RootLayout({
Expand All @@ -40,7 +29,7 @@ export default function RootLayout({
<html lang="en" suppressHydrationWarning>
<body
className={cn(
"min-h-svh bg-background font-sans antialiased",
"bg-background font-sans antialiased",
geistSans.variable,
)}
>
Expand Down
Loading