Skip to content
Closed
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
2 changes: 1 addition & 1 deletion apps/web/scripts/rebuildRenderedHtml.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { markdownService } from "~/lib/services/markdown";
import { logger } from "~/lib/utils/logger";
import { logger } from "@repo/logger";

async function main() {
await markdownService.rebuildAllRenderedHtml();
Expand Down
102 changes: 76 additions & 26 deletions apps/web/src/app/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import { eq } from "drizzle-orm";
import { getServerSession } from "next-auth";
import { authOptions } from "~/lib/auth";
import { Suspense } from "react";
import { PageLocationEditor } from "~/components/wiki/PageLocationEditor";
import { renderWikiMarkdownToHtml } from "~/lib/services/markdown";
import { authorizationService } from "~/lib/services/authorization";
import { MovePageWrapper } from "~/components/wiki/MovePageWrapper";

export const dynamic = "auto";
export const revalidate = 300; // 5 minutes
export const fetchCache = "force-cache";

async function getWikiPageByPath(path: string[]) {
export async function getWikiPageByPath(path: string[]) {
// Decode each path segment individually
const decodedPath = path.map((segment) => decodeURIComponent(segment));
const joinedPath = decodedPath.join("/").replace("%20", " ");
Expand All @@ -36,26 +36,41 @@ async function getWikiPageByPath(path: string[]) {
},
});

if (!page) {
return null; // Return null if page not found
}

// Ensure tags are loaded even if we return early due to cached HTML
const tags = page.tags;

// Check if rendered HTML is up-to-date
if (
page?.renderedHtml &&
page?.renderedHtmlUpdatedAt &&
page?.renderedHtmlUpdatedAt > (page?.updatedAt ?? new Date())
page.renderedHtml &&
page.renderedHtmlUpdatedAt &&
page.renderedHtmlUpdatedAt > (page.updatedAt ?? new Date(0)) // Use epoch if no updatedAt
) {
return page;
// Return page with guaranteed tags
return { ...page, tags };
}

// If page is found and has content, pre-render the markdown to HTML with wiki link validation
if (page && page.content) {
// If page is found and has content, render the markdown to HTML
if (page.content) {
const renderedHtml = await renderWikiMarkdownToHtml(
page.content,
page.id,
page.path
);
page.renderedHtml = renderedHtml;
page.renderedHtmlUpdatedAt = new Date();
// Return page with newly rendered HTML and guaranteed tags
return {
...page,
renderedHtml,
renderedHtmlUpdatedAt: new Date(),
tags, // Ensure tags are included here too
};
}

return page;
// If no content, return page with guaranteed tags
return { ...page, tags };
}

type Params = Promise<{ path: string[] }>;
Expand Down Expand Up @@ -95,6 +110,30 @@ export default async function WikiPageView({
notFound();
}

// Format tags for the WikiPage component
const formattedTags =
page.tags?.map((relation) => ({
id: relation.tag.id,
name: relation.tag.name,
})) || [];

// Determine if the page is currently locked
const isLocked = Boolean(
page.lockedBy &&
page.lockExpiresAt &&
new Date(page.lockExpiresAt) > new Date()
);

// Determine if the current user is the lock owner
const isCurrentUserLockOwner = Boolean(
currentUserId && page.lockedBy && page.lockedBy.id === currentUserId
);

// Format the lockedBy data for the header
const formattedLockedBy = page.lockedBy
? { id: page.lockedBy.id, name: page.lockedBy.name || "Unknown" }
: null;

// Check operation modes
const isEditMode = resolvedSearchParams.edit === "true";
const isMoveMode = resolvedSearchParams.move === "true";
Expand Down Expand Up @@ -129,31 +168,42 @@ export default async function WikiPageView({
if (!canMovePage) {
redirect("/");
}
// Instead of trying to render the PageLocationEditor directly,
// use the MainLayout with a client component wrapper
return (
<MainLayout>
<PageLocationEditor
mode="move"
isOpen={true}
onClose={() => {}}
initialPath={page.path.split("/").slice(0, -1).join("/")}
initialName={page.path.split("/").pop() || ""}
<MainLayout
pageMetadata={{
title: page.title,
path: page.path,
id: page.id,
isLocked: isLocked,
lockedBy: formattedLockedBy,
lockExpiresAt: page.lockExpiresAt?.toISOString() || null,
isCurrentUserLockOwner: isCurrentUserLockOwner,
}}
>
<MovePageWrapper
pageId={page.id}
pageTitle={page.title}
pagePath={page.path}
/>
</MainLayout>
);
}

// Format tags for the WikiPage component
const formattedTags =
page.tags?.map((relation) => ({
id: relation.tag.id,
name: relation.tag.name,
})) || [];

// View mode
return (
<MainLayout>
<MainLayout
pageMetadata={{
title: page.title,
path: page.path,
id: page.id,
isLocked: isLocked,
lockedBy: formattedLockedBy,
lockExpiresAt: page.lockExpiresAt?.toISOString() || null,
isCurrentUserLockOwner: isCurrentUserLockOwner,
}}
>
<WikiPage
id={page.id}
title={page.title}
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/app/admin/groups/[id]/users/add-users-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ export default function AddUsersModal({

// Get all users
const { data: allUsers, isLoading: loadingUsers } = useQuery(
trpc.users.getAll.queryOptions(undefined, {
trpc.admin.users.getAll.queryOptions(undefined, {
enabled: isModalOpen,
})
);

// Get existing group users to exclude them
const { data: groupUsers } = useQuery(
trpc.groups.getGroupUsers.queryOptions(
trpc.admin.groups.getGroupUsers.queryOptions(
{ groupId },
{
enabled: isModalOpen,
Expand Down Expand Up @@ -60,7 +60,7 @@ export default function AddUsersModal({
});

const addUsersMutation = useMutation(
trpc.groups.addUsers.mutationOptions({
trpc.admin.groups.addUsers.mutationOptions({
onSuccess: () => {
toast.success("Users added to group successfully");
setIsModalOpen(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function RemoveUserModal({
const trpc = useTRPC();

const removeUserMutation = useMutation(
trpc.groups.removeUsers.mutationOptions({
trpc.admin.groups.removeUsers.mutationOptions({
onSuccess: () => {
toast.success("User removed from group successfully");
setIsModalOpen(false);
Expand Down
16 changes: 8 additions & 8 deletions apps/web/src/app/admin/groups/group-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { toast } from "sonner";
import { useTRPC } from "~/server/client";
import { useQuery, useMutation } from "@tanstack/react-query";
import { logger } from "~/lib/utils/logger";
import { logger } from "@repo/logger";

interface GroupFormProps {
group?: {
Expand Down Expand Up @@ -67,14 +67,14 @@ export default function GroupForm({

// Fetch available modules and actions
const { data: availableModules = [] } = useQuery(
trpc.permissions.getModules.queryOptions()
trpc.admin.permissions.getModules.queryOptions()
);
const { data: availableActions = [] } = useQuery(
trpc.permissions.getActions.queryOptions()
trpc.admin.permissions.getActions.queryOptions()
);

const createGroup = useMutation(
trpc.groups.create.mutationOptions({
trpc.admin.groups.create.mutationOptions({
onSuccess: () => {
toast.success("Group created successfully");
router.push("/admin/groups");
Expand All @@ -90,7 +90,7 @@ export default function GroupForm({
);

const updateGroup = useMutation(
trpc.groups.update.mutationOptions({
trpc.admin.groups.update.mutationOptions({
onSuccess: () => {
toast.success("Group updated successfully");
router.push("/admin/groups");
Expand All @@ -106,7 +106,7 @@ export default function GroupForm({
);

const addPermissions = useMutation(
trpc.groups.addPermissions.mutationOptions({
trpc.admin.groups.addPermissions.mutationOptions({
onError: (error: unknown) => {
if (error instanceof Error) {
toast.error(error.message);
Expand All @@ -118,7 +118,7 @@ export default function GroupForm({
);

const addModulePermissions = useMutation(
trpc.groups.addModulePermissions.mutationOptions({
trpc.admin.groups.addModulePermissions.mutationOptions({
onError: (error: unknown) => {
if (error instanceof Error) {
toast.error(error.message);
Expand All @@ -130,7 +130,7 @@ export default function GroupForm({
);

const addActionPermissions = useMutation(
trpc.groups.addActionPermissions.mutationOptions({
trpc.admin.groups.addActionPermissions.mutationOptions({
onError: (error: unknown) => {
if (error instanceof Error) {
toast.error(error.message);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/admin/groups/groups-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function GroupsList({ groups: initialGroups }: GroupsListProps) {
const trpc = useTRPC();

const deleteGroup = useMutation(
trpc.groups.delete.mutationOptions({
trpc.admin.groups.delete.mutationOptions({
onSuccess: () => {
toast.success("Group deleted successfully");
// Refresh the page to get updated data
Expand Down
10 changes: 5 additions & 5 deletions apps/web/src/app/admin/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
ClientRequirePermission,
} from "~/components/auth/permission/client";
import { PlusIcon, TrashIcon } from "@heroicons/react/24/outline";
import { logger } from "~/lib/utils/logger";
import { logger } from "@repo/logger";

export default function AdminUsersPage() {
const [searchTerm, setSearchTerm] = useState("");
Expand All @@ -27,7 +27,7 @@ export default function AdminUsersPage() {
// Fetch users
const trpc = useTRPC();
const { data: users, isLoading: usersLoading } = useQuery(
trpc.users.getAll.queryOptions()
trpc.admin.users.getAll.queryOptions()
);

// Infer user type from the fetched data
Expand All @@ -38,12 +38,12 @@ export default function AdminUsersPage() {

// Fetch all groups
const { data: groups, isLoading: groupsLoading } = useQuery(
trpc.groups.getAll.queryOptions()
trpc.admin.groups.getAll.queryOptions()
);

// Mutations
const addToGroupMutation = useMutation(
trpc.groups.addUsers.mutationOptions({
trpc.admin.groups.addUsers.mutationOptions({
onSuccess: () => {
toast.success("User groups updated successfully");
// refetchUserGroups(); // Consider refetching user data here if needed
Expand All @@ -55,7 +55,7 @@ export default function AdminUsersPage() {
);

const removeFromGroupMutation = useMutation(
trpc.groups.removeUsers.mutationOptions({
trpc.admin.groups.removeUsers.mutationOptions({
onSuccess: () => {
toast.success("User removed from group successfully");
// refetchUserGroups(); // Consider refetching user data here if needed
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/api/assets/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type NextRequest, NextResponse } from "next/server";
import { assetService } from "~/lib/services";
import { logger } from "~/lib/utils/logger";
import { logger } from "@repo/logger";
import { checkServerPermission } from "~/lib/utils/server-auth-helpers";

export const dynamic = "force-dynamic";
Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Providers } from "~/providers";
// import { seed } from "@repo/db";
import { PermissionGate } from "~/components/auth/permission/server";
import { LogOutButton } from "~/components/auth/LogOutButton";
import { logger } from "~/lib/utils/logger";
import { logger } from "@repo/logger";

const inter = Inter({
variable: "--font-inter",
Expand Down Expand Up @@ -63,16 +63,16 @@ async function RootLayoutContent({ children }: { children: React.ReactNode }) {

if (userCount === null) {
// Check user count *after* attempting seed if necessary
logger.log("Checking user count...");
logger.debug("Checking user count...");
userCount = await dbService.users.count();
} else {
logger.log("User count already cached:", userCount);
logger.debug("User count already cached:", userCount);
}

const isFirstUser = userCount === 0;

if (isFirstUser) {
logger.log(
logger.debug(
"No users found, directing to registration within RootLayoutContent."
);
return <RegisterPage isFirstUser={true} />;
Expand Down
Loading
Loading