Plug back new org CTA in org dropdown
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -4,8 +4,8 @@ import {
|
||||
type PreloadedQuery,
|
||||
} from "react-relay";
|
||||
import { organizationLayoutQuery } from "./OrganizationLayoutQuery";
|
||||
import { Outlet } from "react-router";
|
||||
import { Layout, Skeleton } from "@probo/ui";
|
||||
import { Link, Outlet } from "react-router";
|
||||
import { Badge, Button, IconPeopleAdd, Layout, Skeleton } from "@probo/ui";
|
||||
import { Sidebar } from "./_components/Sidebar";
|
||||
import { OrganizationDropdown } from "./_components/OrganizationDropdown";
|
||||
import { consoleEnvironment } from "/environments";
|
||||
@@ -13,6 +13,7 @@ import type { OrganizationLayoutQuery } from "./__generated__/OrganizationLayout
|
||||
import { PermissionsProvider } from "/providers/PermissionsProvider";
|
||||
import { SessionDropdown } from "./_components/SessionDropdown";
|
||||
import { Suspense } from "react";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
|
||||
interface OrganizationLayoutProps {
|
||||
queryRef: PreloadedQuery<OrganizationLayoutQuery>;
|
||||
@@ -21,7 +22,9 @@ interface OrganizationLayoutProps {
|
||||
export default function OrganizationLayout(props: OrganizationLayoutProps) {
|
||||
const { queryRef } = props;
|
||||
|
||||
const data = usePreloadedQuery<OrganizationLayoutQuery>(
|
||||
const { __ } = useTranslate();
|
||||
|
||||
const { organization, viewer } = usePreloadedQuery<OrganizationLayoutQuery>(
|
||||
organizationLayoutQuery,
|
||||
queryRef,
|
||||
);
|
||||
@@ -32,10 +35,25 @@ export default function OrganizationLayout(props: OrganizationLayoutProps) {
|
||||
header={
|
||||
<>
|
||||
<div className="mr-auto">
|
||||
<OrganizationDropdown fKey={data.organization} />
|
||||
<OrganizationDropdown
|
||||
organizationFKey={organization}
|
||||
viewerFKey={viewer}
|
||||
/>
|
||||
{viewer.pendingInvitations.totalCount > 0 && (
|
||||
<Link to="/" className="relative" title={__("Invitations")}>
|
||||
<Button variant="tertiary" icon={IconPeopleAdd} />
|
||||
<Badge
|
||||
variant="info"
|
||||
size="sm"
|
||||
className="absolute -top-1 -right-1 min-w-[20px] h-5 flex items-center justify-center"
|
||||
>
|
||||
{viewer.pendingInvitations.totalCount}
|
||||
</Badge>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<Suspense fallback={<Skeleton className="w-32 h-8" />}>
|
||||
<SessionDropdown fKey={data.viewer} />
|
||||
<SessionDropdown fKey={viewer} />
|
||||
</Suspense>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -12,12 +12,13 @@ export const organizationLayoutQuery = graphql`
|
||||
query OrganizationLayoutQuery($organizationId: ID!) {
|
||||
organization: node(id: $organizationId) @required(action: THROW) {
|
||||
... on Organization {
|
||||
...OrganizationDropdownFragment
|
||||
...OrganizationDropdown_organizationFragment
|
||||
}
|
||||
}
|
||||
viewer @required(action: THROW) {
|
||||
pendingInvitations {
|
||||
totalCount
|
||||
...OrganizationDropdown_viewerFragment
|
||||
pendingInvitations @required(action: THROW) {
|
||||
totalCount @required(action: THROW)
|
||||
}
|
||||
...SessionDropdownFragment @arguments(organizationId: $organizationId)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<1d82d885a77675a330799121edb5cb69>>
|
||||
* @generated SignedSource<<09fbc762db2d00eb944a0ef9afe3756d>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -15,13 +15,13 @@ export type OrganizationLayoutQuery$variables = {
|
||||
};
|
||||
export type OrganizationLayoutQuery$data = {
|
||||
readonly organization: {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"OrganizationDropdownFragment">;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"OrganizationDropdown_organizationFragment">;
|
||||
};
|
||||
readonly viewer: {
|
||||
readonly pendingInvitations: {
|
||||
readonly totalCount: number | null | undefined;
|
||||
} | null | undefined;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"SessionDropdownFragment">;
|
||||
readonly totalCount: number;
|
||||
};
|
||||
readonly " $fragmentSpreads": FragmentRefs<"OrganizationDropdown_viewerFragment" | "SessionDropdownFragment">;
|
||||
};
|
||||
};
|
||||
export type OrganizationLayoutQuery = {
|
||||
@@ -47,19 +47,8 @@ v1 = [
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "InvitationConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "pendingInvitations",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "totalCount",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"kind": "ScalarField",
|
||||
"name": "totalCount",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = [
|
||||
@@ -99,7 +88,7 @@ return {
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "OrganizationDropdownFragment"
|
||||
"name": "OrganizationDropdown_organizationFragment"
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
@@ -120,7 +109,31 @@ return {
|
||||
"name": "viewer",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "OrganizationDropdown_viewerFragment"
|
||||
},
|
||||
{
|
||||
"kind": "RequiredField",
|
||||
"field": {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "InvitationConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "pendingInvitations",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"kind": "RequiredField",
|
||||
"field": (v2/*: any*/),
|
||||
"action": "THROW"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
"action": "THROW"
|
||||
},
|
||||
{
|
||||
"args": (v3/*: any*/),
|
||||
"kind": "FragmentSpread",
|
||||
@@ -182,7 +195,18 @@ return {
|
||||
"name": "viewer",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "InvitationConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "pendingInvitations",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -223,16 +247,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "0ebb386f89d19888f18a05c8dc573895",
|
||||
"cacheID": "ca7f41668eb74024237351d0e076819e",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "OrganizationLayoutQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query OrganizationLayoutQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...OrganizationDropdownFragment\n }\n id\n }\n viewer {\n pendingInvitations {\n totalCount\n }\n ...SessionDropdownFragment_4xMPKw\n id\n }\n}\n\nfragment OrganizationDropdownFragment on Organization {\n name\n}\n\nfragment SessionDropdownFragment_4xMPKw on Identity {\n email\n profileFor(organizationId: $organizationId) {\n firstName\n lastName\n id\n }\n}\n"
|
||||
"text": "query OrganizationLayoutQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...OrganizationDropdown_organizationFragment\n }\n id\n }\n viewer {\n ...OrganizationDropdown_viewerFragment\n pendingInvitations {\n totalCount\n }\n ...SessionDropdownFragment_4xMPKw\n id\n }\n}\n\nfragment OrganizationDropdown_organizationFragment on Organization {\n name\n}\n\nfragment OrganizationDropdown_viewerFragment on Identity {\n pendingInvitations {\n totalCount\n }\n}\n\nfragment SessionDropdownFragment_4xMPKw on Identity {\n email\n profileFor(organizationId: $organizationId) {\n firstName\n lastName\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "d3d91888eabb36cc450ca585757b21c7";
|
||||
(node as any).hash = "81b8eb0af21d649268e30c80d16226de";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { useFragment, useQueryLoader } from "react-relay";
|
||||
import { graphql } from "relay-runtime";
|
||||
import type { OrganizationDropdownFragment$key } from "./__generated__/OrganizationDropdownFragment.graphql";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
DropdownSeparator,
|
||||
IconChevronGrabberVertical,
|
||||
IconMagnifyingGlass,
|
||||
IconPeopleAdd,
|
||||
IconPlusLarge,
|
||||
Input,
|
||||
} from "@probo/ui";
|
||||
import { Suspense, useCallback, useState } from "react";
|
||||
@@ -16,22 +19,43 @@ import {
|
||||
organizationDropdownMenuQuery,
|
||||
} from "./OrganizationDropdownMenu";
|
||||
import type { OrganizationDropdownMenuQuery } from "./__generated__/OrganizationDropdownMenuQuery.graphql";
|
||||
import { Link } from "react-router";
|
||||
import type { OrganizationDropdown_organizationFragment$key } from "./__generated__/OrganizationDropdown_organizationFragment.graphql";
|
||||
import type { OrganizationDropdown_viewerFragment$key } from "./__generated__/OrganizationDropdown_viewerFragment.graphql";
|
||||
|
||||
const fragment = graphql`
|
||||
fragment OrganizationDropdownFragment on Organization {
|
||||
const organizationFragment = graphql`
|
||||
fragment OrganizationDropdown_organizationFragment on Organization {
|
||||
name
|
||||
}
|
||||
`;
|
||||
const viewerFragment = graphql`
|
||||
fragment OrganizationDropdown_viewerFragment on Identity {
|
||||
pendingInvitations @required(action: THROW) {
|
||||
totalCount @required(action: THROW)
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export function OrganizationDropdown(props: {
|
||||
fKey: OrganizationDropdownFragment$key;
|
||||
organizationFKey: OrganizationDropdown_organizationFragment$key;
|
||||
viewerFKey: OrganizationDropdown_viewerFragment$key;
|
||||
}) {
|
||||
const { fKey } = props;
|
||||
const { organizationFKey, viewerFKey } = props;
|
||||
|
||||
const { __ } = useTranslate();
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const currentOrganization = useFragment(fragment, fKey);
|
||||
const currentOrganization =
|
||||
useFragment<OrganizationDropdown_organizationFragment$key>(
|
||||
organizationFragment,
|
||||
organizationFKey,
|
||||
);
|
||||
const {
|
||||
pendingInvitations: { totalCount: pendingInvitationCount },
|
||||
} = useFragment<OrganizationDropdown_viewerFragment$key>(
|
||||
viewerFragment,
|
||||
viewerFKey,
|
||||
);
|
||||
const [queryRef, loadQuery] = useQueryLoader<OrganizationDropdownMenuQuery>(
|
||||
organizationDropdownMenuQuery,
|
||||
);
|
||||
@@ -83,6 +107,23 @@ export function OrganizationDropdown(props: {
|
||||
)}
|
||||
</div>
|
||||
<DropdownSeparator />
|
||||
{pendingInvitationCount > 0 && (
|
||||
<DropdownItem asChild>
|
||||
<Link to="/">
|
||||
<IconPeopleAdd size={16} />
|
||||
<span className="flex-1">{__("Invitations")}</span>
|
||||
<Badge variant="info" size="sm">
|
||||
{pendingInvitationCount}
|
||||
</Badge>
|
||||
</Link>
|
||||
</DropdownItem>
|
||||
)}
|
||||
<DropdownItem asChild>
|
||||
<Link to="/organizations/new">
|
||||
<IconPlusLarge size={16} />
|
||||
{__("Add organization")}
|
||||
</Link>
|
||||
</DropdownItem>
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<06f02e43b64c316083067f5b3978a08a>>
|
||||
* @generated SignedSource<<1d2465517ea2dcfa99fb3dd8757fe980>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,20 +10,20 @@
|
||||
|
||||
import { ReaderFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type OrganizationDropdownFragment$data = {
|
||||
export type OrganizationDropdown_organizationFragment$data = {
|
||||
readonly name: string;
|
||||
readonly " $fragmentType": "OrganizationDropdownFragment";
|
||||
readonly " $fragmentType": "OrganizationDropdown_organizationFragment";
|
||||
};
|
||||
export type OrganizationDropdownFragment$key = {
|
||||
readonly " $data"?: OrganizationDropdownFragment$data;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"OrganizationDropdownFragment">;
|
||||
export type OrganizationDropdown_organizationFragment$key = {
|
||||
readonly " $data"?: OrganizationDropdown_organizationFragment$data;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"OrganizationDropdown_organizationFragment">;
|
||||
};
|
||||
|
||||
const node: ReaderFragment = {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "OrganizationDropdownFragment",
|
||||
"name": "OrganizationDropdown_organizationFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
@@ -37,6 +37,6 @@ const node: ReaderFragment = {
|
||||
"abstractKey": null
|
||||
};
|
||||
|
||||
(node as any).hash = "9f19581f86736e6345912284668a8f25";
|
||||
(node as any).hash = "8e6d0c702f821670315b5bde55e2556a";
|
||||
|
||||
export default node;
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @generated SignedSource<<d4b9efa7b9092ceb3f995507108a68e3>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ReaderFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type OrganizationDropdown_viewerFragment$data = {
|
||||
readonly pendingInvitations: {
|
||||
readonly totalCount: number;
|
||||
};
|
||||
readonly " $fragmentType": "OrganizationDropdown_viewerFragment";
|
||||
};
|
||||
export type OrganizationDropdown_viewerFragment$key = {
|
||||
readonly " $data"?: OrganizationDropdown_viewerFragment$data;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"OrganizationDropdown_viewerFragment">;
|
||||
};
|
||||
|
||||
const node: ReaderFragment = {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "OrganizationDropdown_viewerFragment",
|
||||
"selections": [
|
||||
{
|
||||
"kind": "RequiredField",
|
||||
"field": {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "InvitationConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "pendingInvitations",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"kind": "RequiredField",
|
||||
"field": {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "totalCount",
|
||||
"storageKey": null
|
||||
},
|
||||
"action": "THROW"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
"action": "THROW"
|
||||
}
|
||||
],
|
||||
"type": "Identity",
|
||||
"abstractKey": null
|
||||
};
|
||||
|
||||
(node as any).hash = "ce947f812c95b74e9f250b8d5821ebb0";
|
||||
|
||||
export default node;
|
||||
Reference in New Issue
Block a user