Add CurrentUser context and use it in documents

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2026-01-02 16:22:11 +01:00
committed by Bryan Frimin
parent 26371857e9
commit ecf27751ac
13 changed files with 139 additions and 194 deletions

View File

@@ -8,6 +8,7 @@ import { SessionDropdown } from "./_components/SessionDropdown";
import { Suspense } from "react";
import { useTranslate } from "@probo/i18n";
import { CoreRelayProvider } from "/providers/CoreRelayProvider";
import { CurrentUser } from "/providers/CurrentUser";
export const membershipLayoutQuery = graphql`
query MembershipLayoutQuery($organizationId: ID!, $hideSidebar: Boolean!) {
@@ -19,10 +20,14 @@ export const membershipLayoutQuery = graphql`
...SidebarFragment @skip(if: $hideSidebar)
viewerMembership @required(action: THROW) {
role
profile @required(action: THROW) {
fullName
}
}
}
}
viewer @required(action: THROW) {
email
...MembershipsDropdown_viewerFragment
pendingInvitations @required(action: THROW) {
totalCount @required(action: THROW)
@@ -77,7 +82,15 @@ export function MembershipLayout(props: {
sidebar={!hideSidebar && <Sidebar fKey={organization} />}
>
<CoreRelayProvider>
<Outlet context={organization.viewerMembership.role} />
<CurrentUser
value={{
email: viewer.email,
fullName: organization.viewerMembership.profile.fullName,
role: organization.viewerMembership.role,
}}
>
<Outlet context={organization.viewerMembership.role} />
</CurrentUser>
</CoreRelayProvider>
</Layout>
);

View File

@@ -1,4 +1,4 @@
import { getAssignableRoles, Role, sprintf } from "@probo/helpers";
import { getAssignableRoles, sprintf } from "@probo/helpers";
import { useTranslate } from "@probo/i18n";
import {
DialogContent,
@@ -10,11 +10,12 @@ import {
Spinner,
Dialog,
} from "@probo/ui";
import { useState } from "react";
import { use, useState } from "react";
import { graphql } from "relay-runtime";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { useOrganizationId } from "/hooks/useOrganizationId";
import type { MemberListItemFragment$data } from "/__generated__/iam/MemberListItemFragment.graphql";
import { CurrentUser } from "/providers/CurrentUser";
const updateMembershipMutation = graphql`
mutation EditMemberDialog_updateMutation($input: UpdateMembershipInput!) {
@@ -28,16 +29,16 @@ const updateMembershipMutation = graphql`
`;
export function EditMemberDialog(props: {
currentRole: Role;
membership: MemberListItemFragment$data;
onClose: () => void;
}) {
const { currentRole, membership, onClose } = props;
const { membership, onClose } = props;
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const availableRoles = getAssignableRoles(currentRole);
const { role } = use(CurrentUser);
const availableRoles = getAssignableRoles(role);
const [selectedRole, setSelectedRole] = useState<string>(membership.role);

View File

@@ -19,7 +19,6 @@ const fragment = graphql`
before: { type: "CursorKey", defaultValue: null }
last: { type: "Int", defaultValue: null }
) {
...MemberListItem_currentRoleFragment
members(
first: $first
after: $after
@@ -94,7 +93,6 @@ export function MemberList(props: { fKey: MemberListFragment$key }) {
key={membership.id}
fKey={membership}
onRefetch={refetchMemberships}
viewerFKey={membersPagination.data}
/>
))
)}

View File

@@ -10,15 +10,15 @@ import {
useConfirm,
} from "@probo/ui";
import clsx from "clsx";
import { useState } from "react";
import { use, useState } from "react";
import { useFragment } from "react-relay";
import { graphql } from "relay-runtime";
import type { MemberListItemFragment$key } from "/__generated__/iam/MemberListItemFragment.graphql";
import type { MemberListItem_currentRoleFragment$key } from "/__generated__/iam/MemberListItem_currentRoleFragment.graphql";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { useOrganizationId } from "/hooks/useOrganizationId";
import { sprintf } from "@probo/helpers";
import { EditMemberDialog } from "./EditMemberDialog";
import { CurrentUser } from "/providers/CurrentUser";
const fragment = graphql`
fragment MemberListItemFragment on Membership {
@@ -36,14 +36,6 @@ const fragment = graphql`
}
`;
const currentRoleFragment = graphql`
fragment MemberListItem_currentRoleFragment on Organization {
viewerMembership @required(action: THROW) {
role
}
}
`;
const removeMemberMutation = graphql`
mutation MemberListItem_removeMutation(
$input: RemoveMemberInput!
@@ -58,10 +50,9 @@ const removeMemberMutation = graphql`
export function MemberListItem(props: {
connectionId: string;
fKey: MemberListItemFragment$key;
viewerFKey: MemberListItem_currentRoleFragment$key;
onRefetch: () => void;
}) {
const { fKey, connectionId, viewerFKey } = props;
const { fKey, connectionId } = props;
const organizationId = useOrganizationId();
const { __ } = useTranslate();
@@ -69,15 +60,10 @@ export function MemberListItem(props: {
const [dialogOpen, setDialogOpen] = useState(false);
const membership = useFragment<MemberListItemFragment$key>(fragment, fKey);
const { viewerMembership } =
useFragment<MemberListItem_currentRoleFragment$key>(
currentRoleFragment,
viewerFKey,
);
const { role } = use(CurrentUser);
// Only OWNER can edit OWNER members
const canEditThisRole =
membership.role === "OWNER" ? viewerMembership.role === "OWNER" : true;
const canEditThisRole = membership.role === "OWNER" ? role === "OWNER" : true;
const [removeMembership, isRemoving] = useMutationWithToasts(
removeMemberMutation,
@@ -162,7 +148,6 @@ export function MemberListItem(props: {
{dialogOpen && (
<EditMemberDialog
currentRole={viewerMembership.role}
onClose={() => setDialogOpen(false)}
membership={membership}
/>

View File

@@ -65,7 +65,7 @@ import {
PdfDownloadDialog,
type PdfDownloadDialogRef,
} from "/components/documents/PdfDownloadDialog";
import { useRef, useState } from "react";
import { use, useRef, useState } from "react";
import type { NodeOf } from "/types.ts";
import clsx from "clsx";
import { PeopleSelectField } from "/components/form/PeopleSelectField";
@@ -74,6 +74,7 @@ import { DocumentTypeOptions } from "/components/form/DocumentTypeOptions";
import { DocumentClassificationOptions } from "/components/form/DocumentClassificationOptions";
import { z } from "zod";
import { useFormWithSchema } from "/hooks/useFormWithSchema";
import { CurrentUser } from "/providers/CurrentUser";
type Props = {
queryRef: PreloadedQuery<DocumentGraphNodeQuery>;
@@ -92,12 +93,6 @@ const documentFragment = graphql`
canUpdate: permission(action: "core:document:update")
canDelete: permission(action: "core:document:delete")
canPublish: permission(action: "core:document-version:publish")
# canSendSigningNotifications: permission(
# action: "core:document:send-signing-notifications"
# )
# canRequestSignatures: permission(
# action: "core:document-version:request-signature"
# )
...DocumentControlsTabFragment
controlsInfo: controls(first: 0) {
totalCount
@@ -187,15 +182,6 @@ const documentUpdateSchema = z.object({
classification: z.enum(documentClassifications),
});
// FIXME
// const UserEmailQuery = graphql`
// query DocumentDetailPageUserEmailQuery {
// viewer {
// email
// }
// }
// `;
export default function DocumentDetailPage(props: Props) {
const { versionId } = useParams<{ versionId?: string }>();
const node = usePreloadedQuery(documentNodeQuery, props.queryRef).node;
@@ -237,11 +223,7 @@ export default function DocumentDetailPage(props: Props) {
},
);
// const userEmailData = useLazyLoadQuery<DocumentDetailPageUserEmailQuery>(
// UserEmailQuery,
// {}
// );
// const defaultEmail = userEmailData.viewer.user.email;
const { email: defaultEmail } = use(CurrentUser);
const [updateDocument, isUpdatingDocument] =
useMutationWithToasts<DocumentDetailPageUpdateMutation>(
updateDocumentMutation,
@@ -454,7 +436,7 @@ export default function DocumentDetailPage(props: Props) {
ref={pdfDownloadDialogRef}
onDownload={handleDownloadPdf}
isLoading={isExporting}
// defaultEmail={defaultEmail}
defaultEmail={defaultEmail}
>
{null}
</PdfDownloadDialog>