Order organization by name
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -30,28 +30,49 @@ import {
|
|||||||
DropdownItem,
|
DropdownItem,
|
||||||
IconChevronGrabberVertical,
|
IconChevronGrabberVertical,
|
||||||
IconPlusLarge,
|
IconPlusLarge,
|
||||||
|
IconChevronDown,
|
||||||
Avatar,
|
Avatar,
|
||||||
} from "@probo/ui";
|
} from "@probo/ui";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
import { useLazyLoadQuery } from "react-relay";
|
import { useLazyLoadQuery, usePaginationFragment } from "react-relay";
|
||||||
import type { MainLayoutQuery as MainLayoutQueryType } from "./__generated__/MainLayoutQuery.graphql";
|
import type { MainLayoutQuery as MainLayoutQueryType } from "./__generated__/MainLayoutQuery.graphql";
|
||||||
import { Suspense } from "react";
|
import type { MainLayout_OrganizationSelector_viewer$key } from "./__generated__/MainLayout_OrganizationSelector_viewer.graphql";
|
||||||
|
import { Suspense, useState } from "react";
|
||||||
import { useToast } from "@probo/ui";
|
import { useToast } from "@probo/ui";
|
||||||
import { ErrorBoundary } from "react-error-boundary";
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
import { PageError } from "/components/PageError";
|
import { PageError } from "/components/PageError";
|
||||||
import { buildEndpoint } from "/providers/RelayProviders";
|
import { buildEndpoint } from "/providers/RelayProviders";
|
||||||
|
|
||||||
const MainLayoutQuery = graphql`
|
const MainLayoutQuery = graphql`
|
||||||
query MainLayoutQuery {
|
query MainLayoutQuery($organizationId: ID!) {
|
||||||
viewer {
|
viewer {
|
||||||
id
|
id
|
||||||
user {
|
user {
|
||||||
fullName
|
fullName
|
||||||
email
|
email
|
||||||
}
|
}
|
||||||
organizations(first: 25) @connection(key: "MainLayout_organizations") {
|
...MainLayout_OrganizationSelector_viewer
|
||||||
__id
|
}
|
||||||
|
organization: node(id: $organizationId) {
|
||||||
|
... on Organization {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
logoUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const OrganizationSelectorFragment = graphql`
|
||||||
|
fragment MainLayout_OrganizationSelector_viewer on Viewer
|
||||||
|
@refetchable(queryName: "MainLayoutOrganizationSelectorPaginationQuery")
|
||||||
|
@argumentDefinitions(
|
||||||
|
first: { type: "Int", defaultValue: 25 }
|
||||||
|
after: { type: "CursorKey" }
|
||||||
|
) {
|
||||||
|
organizations(first: $first, after: $after, orderBy: {field: NAME, direction: ASC})
|
||||||
|
@connection(key: "MainLayout_OrganizationSelector_organizations") {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
@@ -59,6 +80,9 @@ const MainLayoutQuery = graphql`
|
|||||||
logoUrl
|
logoUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,11 +107,11 @@ export function MainLayout() {
|
|||||||
<>
|
<>
|
||||||
<div className="mr-auto">
|
<div className="mr-auto">
|
||||||
<Suspense fallback={<Skeleton className="w-20 h-8" />}>
|
<Suspense fallback={<Skeleton className="w-20 h-8" />}>
|
||||||
<OrganizationSelector organizationId={organizationId} />
|
<OrganizationSelectorWrapper organizationId={organizationId} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
<Suspense fallback={<Skeleton className="w-32 h-8" />}>
|
<Suspense fallback={<Skeleton className="w-32 h-8" />}>
|
||||||
<UserDropdown />
|
<UserDropdown organizationId={organizationId} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
@@ -188,10 +212,10 @@ export function MainLayout() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UserDropdown() {
|
function UserDropdown({ organizationId }: { organizationId: string }) {
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const user = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, {}).viewer
|
const user = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, { organizationId }).viewer
|
||||||
.user;
|
.user;
|
||||||
|
|
||||||
const handleLogout: React.MouseEventHandler<HTMLAnchorElement> = async (
|
const handleLogout: React.MouseEventHandler<HTMLAnchorElement> = async (
|
||||||
@@ -242,16 +266,40 @@ function UserDropdown() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function OrganizationSelector({ organizationId }: { organizationId: string }) {
|
function OrganizationSelectorWrapper({ organizationId }: { organizationId: string }) {
|
||||||
const organizations = useLazyLoadQuery<MainLayoutQueryType>(
|
const data = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, { organizationId });
|
||||||
MainLayoutQuery,
|
return <OrganizationSelector viewer={data.viewer} currentOrganization={data.organization} />;
|
||||||
{}
|
}
|
||||||
).viewer.organizations.edges.map((edge) => edge.node);
|
|
||||||
const currentOrganization = organizations.find(
|
function OrganizationSelector({
|
||||||
(organization) => organization.id === organizationId
|
viewer,
|
||||||
);
|
currentOrganization
|
||||||
|
}: {
|
||||||
|
viewer: MainLayout_OrganizationSelector_viewer$key;
|
||||||
|
currentOrganization: MainLayoutQueryType["response"]["organization"];
|
||||||
|
}) {
|
||||||
|
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
|
|
||||||
|
const { data, loadNext, hasNext } = usePaginationFragment(
|
||||||
|
OrganizationSelectorFragment,
|
||||||
|
viewer
|
||||||
|
);
|
||||||
|
|
||||||
|
const organizations = data.organizations.edges.map((edge) => edge.node);
|
||||||
|
|
||||||
|
const handleLoadMore = (e?: React.MouseEvent) => {
|
||||||
|
e?.preventDefault();
|
||||||
|
e?.stopPropagation();
|
||||||
|
|
||||||
|
if (hasNext && !isLoadingMore) {
|
||||||
|
setIsLoadingMore(true);
|
||||||
|
loadNext(25, {
|
||||||
|
onComplete: () => setIsLoadingMore(false),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
toggle={
|
toggle={
|
||||||
@@ -260,15 +308,15 @@ function OrganizationSelector({ organizationId }: { organizationId: string }) {
|
|||||||
variant="tertiary"
|
variant="tertiary"
|
||||||
iconAfter={IconChevronGrabberVertical}
|
iconAfter={IconChevronGrabberVertical}
|
||||||
>
|
>
|
||||||
{currentOrganization?.name}
|
{currentOrganization?.name || ""}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
<div className="max-h-150 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent hover:scrollbar-thumb-gray-400">
|
||||||
{organizations.map((organization) => (
|
{organizations.map((organization) => (
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
asChild
|
asChild
|
||||||
key={organization.id}
|
key={organization.id}
|
||||||
icon={IconCircleQuestionmark}
|
|
||||||
>
|
>
|
||||||
<Link to={`/organizations/${organization.id}`}>
|
<Link to={`/organizations/${organization.id}`}>
|
||||||
<Avatar src={organization.logoUrl} name={organization.name} />
|
<Avatar src={organization.logoUrl} name={organization.name} />
|
||||||
@@ -276,6 +324,24 @@ function OrganizationSelector({ organizationId }: { organizationId: string }) {
|
|||||||
</Link>
|
</Link>
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
))}
|
))}
|
||||||
|
{hasNext && (
|
||||||
|
<div className="px-3 py-1 flex justify-center">
|
||||||
|
<Button
|
||||||
|
variant="tertiary"
|
||||||
|
onClick={handleLoadMore}
|
||||||
|
onMouseDown={(e: React.MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
className="mx-auto"
|
||||||
|
icon={IconChevronDown}
|
||||||
|
disabled={isLoadingMore}
|
||||||
|
>
|
||||||
|
{isLoadingMore ? __("Loading...") : __("Show More")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<DropdownSeparator />
|
<DropdownSeparator />
|
||||||
<DropdownItem asChild icon={IconPlusLarge}>
|
<DropdownItem asChild icon={IconPlusLarge}>
|
||||||
<Link to="/organizations/new">
|
<Link to="/organizations/new">
|
||||||
|
|||||||
230
apps/console/src/layouts/__generated__/MainLayoutOrganizationSelectorPaginationQuery.graphql.ts
generated
Normal file
230
apps/console/src/layouts/__generated__/MainLayoutOrganizationSelectorPaginationQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<92c96c7b8a58554e9fb99b86489e13d4>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
import { FragmentRefs } from "relay-runtime";
|
||||||
|
export type MainLayoutOrganizationSelectorPaginationQuery$variables = {
|
||||||
|
after?: any | null | undefined;
|
||||||
|
first?: number | null | undefined;
|
||||||
|
};
|
||||||
|
export type MainLayoutOrganizationSelectorPaginationQuery$data = {
|
||||||
|
readonly viewer: {
|
||||||
|
readonly " $fragmentSpreads": FragmentRefs<"MainLayout_OrganizationSelector_viewer">;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type MainLayoutOrganizationSelectorPaginationQuery = {
|
||||||
|
response: MainLayoutOrganizationSelectorPaginationQuery$data;
|
||||||
|
variables: MainLayoutOrganizationSelectorPaginationQuery$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "after"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultValue": 25,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "first"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = {
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "after",
|
||||||
|
"variableName": "after"
|
||||||
|
},
|
||||||
|
v2 = {
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "first",
|
||||||
|
"variableName": "first"
|
||||||
|
},
|
||||||
|
v3 = [
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v2/*: any*/),
|
||||||
|
{
|
||||||
|
"kind": "Literal",
|
||||||
|
"name": "orderBy",
|
||||||
|
"value": {
|
||||||
|
"direction": "ASC",
|
||||||
|
"field": "NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v4 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "MainLayoutOrganizationSelectorPaginationQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Viewer",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "viewer",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"args": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v2/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "FragmentSpread",
|
||||||
|
"name": "MainLayout_OrganizationSelector_viewer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "MainLayoutOrganizationSelectorPaginationQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Viewer",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "viewer",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v3/*: any*/),
|
||||||
|
"concreteType": "OrganizationConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "organizations",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "OrganizationEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Organization",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v4/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "name",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "logoUrl",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "PageInfo",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "pageInfo",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasNextPage",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "endCursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v3/*: any*/),
|
||||||
|
"filters": [
|
||||||
|
"orderBy"
|
||||||
|
],
|
||||||
|
"handle": "connection",
|
||||||
|
"key": "MainLayout_OrganizationSelector_organizations",
|
||||||
|
"kind": "LinkedHandle",
|
||||||
|
"name": "organizations"
|
||||||
|
},
|
||||||
|
(v4/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "57fa65c9d5f23210b606fbf0b2005fb8",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "MainLayoutOrganizationSelectorPaginationQuery",
|
||||||
|
"operationKind": "query",
|
||||||
|
"text": "query MainLayoutOrganizationSelectorPaginationQuery(\n $after: CursorKey\n $first: Int = 25\n) {\n viewer {\n ...MainLayout_OrganizationSelector_viewer_2HEEH6\n id\n }\n}\n\nfragment MainLayout_OrganizationSelector_viewer_2HEEH6 on Viewer {\n organizations(first: $first, after: $after, orderBy: {field: NAME, direction: ASC}) {\n edges {\n node {\n id\n name\n logoUrl\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "0dc2841aeeb6ba5291cb45d8644ec4af";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<d411922830ba632f8c48c98caa435a22>>
|
* @generated SignedSource<<0719379cc0124f36eb1810ad24b2ae5a>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -9,24 +9,23 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|
||||||
import { ConcreteRequest } from 'relay-runtime';
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
export type MainLayoutQuery$variables = Record<PropertyKey, never>;
|
import { FragmentRefs } from "relay-runtime";
|
||||||
|
export type MainLayoutQuery$variables = {
|
||||||
|
organizationId: string;
|
||||||
|
};
|
||||||
export type MainLayoutQuery$data = {
|
export type MainLayoutQuery$data = {
|
||||||
|
readonly organization: {
|
||||||
|
readonly id?: string;
|
||||||
|
readonly logoUrl?: string | null | undefined;
|
||||||
|
readonly name?: string;
|
||||||
|
};
|
||||||
readonly viewer: {
|
readonly viewer: {
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
readonly organizations: {
|
|
||||||
readonly __id: string;
|
|
||||||
readonly edges: ReadonlyArray<{
|
|
||||||
readonly node: {
|
|
||||||
readonly id: string;
|
|
||||||
readonly logoUrl: string | null | undefined;
|
|
||||||
readonly name: string;
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
readonly user: {
|
readonly user: {
|
||||||
readonly email: string;
|
readonly email: string;
|
||||||
readonly fullName: string;
|
readonly fullName: string;
|
||||||
};
|
};
|
||||||
|
readonly " $fragmentSpreads": FragmentRefs<"MainLayout_OrganizationSelector_viewer">;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
export type MainLayoutQuery = {
|
export type MainLayoutQuery = {
|
||||||
@@ -35,28 +34,176 @@ export type MainLayoutQuery = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const node: ConcreteRequest = (function(){
|
const node: ConcreteRequest = (function(){
|
||||||
var v0 = {
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "organizationId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v1 = {
|
v2 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "fullName",
|
"name": "fullName",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v2 = {
|
v3 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "email",
|
"name": "email",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v3 = [
|
v4 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "id",
|
||||||
|
"variableName": "organizationId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v5 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "name",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v6 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "logoUrl",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v7 = [
|
||||||
|
{
|
||||||
|
"kind": "Literal",
|
||||||
|
"name": "first",
|
||||||
|
"value": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Literal",
|
||||||
|
"name": "orderBy",
|
||||||
|
"value": {
|
||||||
|
"direction": "ASC",
|
||||||
|
"field": "NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v8 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "MainLayoutQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Viewer",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "viewer",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "User",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "user",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
(v3/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": null,
|
||||||
|
"kind": "FragmentSpread",
|
||||||
|
"name": "MainLayout_OrganizationSelector_viewer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": "organization",
|
||||||
|
"args": (v4/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/)
|
||||||
|
],
|
||||||
|
"type": "Organization",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "MainLayoutQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Viewer",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "viewer",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "User",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "user",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
(v3/*: any*/),
|
||||||
|
(v1/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v7/*: any*/),
|
||||||
|
"concreteType": "OrganizationConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "organizations",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -73,28 +220,10 @@ v3 = [
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v0/*: any*/),
|
(v1/*: any*/),
|
||||||
{
|
(v5/*: any*/),
|
||||||
"alias": null,
|
(v6/*: any*/),
|
||||||
"args": null,
|
(v8/*: any*/)
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "name",
|
|
||||||
"storageKey": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "logoUrl",
|
|
||||||
"storageKey": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "__typename",
|
|
||||||
"storageKey": null
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
@@ -116,165 +245,75 @@ v3 = [
|
|||||||
"name": "pageInfo",
|
"name": "pageInfo",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "endCursor",
|
|
||||||
"storageKey": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "hasNextPage",
|
"name": "hasNextPage",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
|
||||||
],
|
|
||||||
"storageKey": null
|
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"kind": "ClientExtension",
|
|
||||||
"selections": [
|
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "__id",
|
"name": "endCursor",
|
||||||
"storageKey": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
v4 = [
|
|
||||||
{
|
|
||||||
"kind": "Literal",
|
|
||||||
"name": "first",
|
|
||||||
"value": 25
|
|
||||||
}
|
|
||||||
];
|
|
||||||
return {
|
|
||||||
"fragment": {
|
|
||||||
"argumentDefinitions": [],
|
|
||||||
"kind": "Fragment",
|
|
||||||
"metadata": null,
|
|
||||||
"name": "MainLayoutQuery",
|
|
||||||
"selections": [
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"concreteType": "Viewer",
|
|
||||||
"kind": "LinkedField",
|
|
||||||
"name": "viewer",
|
|
||||||
"plural": false,
|
|
||||||
"selections": [
|
|
||||||
(v0/*: any*/),
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"concreteType": "User",
|
|
||||||
"kind": "LinkedField",
|
|
||||||
"name": "user",
|
|
||||||
"plural": false,
|
|
||||||
"selections": [
|
|
||||||
(v1/*: any*/),
|
|
||||||
(v2/*: any*/)
|
|
||||||
],
|
|
||||||
"storageKey": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"alias": "organizations",
|
|
||||||
"args": null,
|
|
||||||
"concreteType": "OrganizationConnection",
|
|
||||||
"kind": "LinkedField",
|
|
||||||
"name": "__MainLayout_organizations_connection",
|
|
||||||
"plural": false,
|
|
||||||
"selections": (v3/*: any*/),
|
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"type": "Query",
|
"storageKey": "organizations(first:25,orderBy:{\"direction\":\"ASC\",\"field\":\"NAME\"})"
|
||||||
"abstractKey": null
|
|
||||||
},
|
|
||||||
"kind": "Request",
|
|
||||||
"operation": {
|
|
||||||
"argumentDefinitions": [],
|
|
||||||
"kind": "Operation",
|
|
||||||
"name": "MainLayoutQuery",
|
|
||||||
"selections": [
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"concreteType": "Viewer",
|
|
||||||
"kind": "LinkedField",
|
|
||||||
"name": "viewer",
|
|
||||||
"plural": false,
|
|
||||||
"selections": [
|
|
||||||
(v0/*: any*/),
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"concreteType": "User",
|
|
||||||
"kind": "LinkedField",
|
|
||||||
"name": "user",
|
|
||||||
"plural": false,
|
|
||||||
"selections": [
|
|
||||||
(v1/*: any*/),
|
|
||||||
(v2/*: any*/),
|
|
||||||
(v0/*: any*/)
|
|
||||||
],
|
|
||||||
"storageKey": null
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v4/*: any*/),
|
"args": (v7/*: any*/),
|
||||||
"concreteType": "OrganizationConnection",
|
"filters": [
|
||||||
"kind": "LinkedField",
|
"orderBy"
|
||||||
"name": "organizations",
|
],
|
||||||
"plural": false,
|
|
||||||
"selections": (v3/*: any*/),
|
|
||||||
"storageKey": "organizations(first:25)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": (v4/*: any*/),
|
|
||||||
"filters": null,
|
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "MainLayout_organizations",
|
"key": "MainLayout_OrganizationSelector_organizations",
|
||||||
"kind": "LinkedHandle",
|
"kind": "LinkedHandle",
|
||||||
"name": "organizations"
|
"name": "organizations"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": "organization",
|
||||||
|
"args": (v4/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v8/*: any*/),
|
||||||
|
(v1/*: any*/),
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/)
|
||||||
|
],
|
||||||
|
"type": "Organization",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "9ab80df970b8fa7c4eabff75a6730ec5",
|
"cacheID": "6287440397ef427d84f8734b0953784c",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"connection": [
|
|
||||||
{
|
|
||||||
"count": null,
|
|
||||||
"cursor": null,
|
|
||||||
"direction": "forward",
|
|
||||||
"path": [
|
|
||||||
"viewer",
|
|
||||||
"organizations"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"name": "MainLayoutQuery",
|
"name": "MainLayoutQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query MainLayoutQuery {\n viewer {\n id\n user {\n fullName\n email\n id\n }\n organizations(first: 25) {\n edges {\n node {\n id\n name\n logoUrl\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n}\n"
|
"text": "query MainLayoutQuery(\n $organizationId: ID!\n) {\n viewer {\n id\n user {\n fullName\n email\n id\n }\n ...MainLayout_OrganizationSelector_viewer\n }\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n name\n logoUrl\n }\n id\n }\n}\n\nfragment MainLayout_OrganizationSelector_viewer on Viewer {\n organizations(first: 25, orderBy: {field: NAME, direction: ASC}) {\n edges {\n node {\n id\n name\n logoUrl\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "fc37d1b70f1a239abb4c959d47ee28fd";
|
(node as any).hash = "aaaca58a896839aa85ce7c2fcf75de39";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
190
apps/console/src/layouts/__generated__/MainLayout_OrganizationSelector_viewer.graphql.ts
generated
Normal file
190
apps/console/src/layouts/__generated__/MainLayout_OrganizationSelector_viewer.graphql.ts
generated
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<2eda1054dbabd2bb5e45d8db5c7a01fc>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ReaderFragment } from 'relay-runtime';
|
||||||
|
import { FragmentRefs } from "relay-runtime";
|
||||||
|
export type MainLayout_OrganizationSelector_viewer$data = {
|
||||||
|
readonly organizations: {
|
||||||
|
readonly edges: ReadonlyArray<{
|
||||||
|
readonly node: {
|
||||||
|
readonly id: string;
|
||||||
|
readonly logoUrl: string | null | undefined;
|
||||||
|
readonly name: string;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
readonly pageInfo: {
|
||||||
|
readonly endCursor: any | null | undefined;
|
||||||
|
readonly hasNextPage: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
readonly " $fragmentType": "MainLayout_OrganizationSelector_viewer";
|
||||||
|
};
|
||||||
|
export type MainLayout_OrganizationSelector_viewer$key = {
|
||||||
|
readonly " $data"?: MainLayout_OrganizationSelector_viewer$data;
|
||||||
|
readonly " $fragmentSpreads": FragmentRefs<"MainLayout_OrganizationSelector_viewer">;
|
||||||
|
};
|
||||||
|
|
||||||
|
import MainLayoutOrganizationSelectorPaginationQuery_graphql from './MainLayoutOrganizationSelectorPaginationQuery.graphql';
|
||||||
|
|
||||||
|
const node: ReaderFragment = (function(){
|
||||||
|
var v0 = [
|
||||||
|
"organizations"
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "after"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultValue": 25,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "first"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": {
|
||||||
|
"connection": [
|
||||||
|
{
|
||||||
|
"count": "first",
|
||||||
|
"cursor": "after",
|
||||||
|
"direction": "forward",
|
||||||
|
"path": (v0/*: any*/)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refetch": {
|
||||||
|
"connection": {
|
||||||
|
"forward": {
|
||||||
|
"count": "first",
|
||||||
|
"cursor": "after"
|
||||||
|
},
|
||||||
|
"backward": null,
|
||||||
|
"path": (v0/*: any*/)
|
||||||
|
},
|
||||||
|
"fragmentPathInResult": [
|
||||||
|
"viewer"
|
||||||
|
],
|
||||||
|
"operation": MainLayoutOrganizationSelectorPaginationQuery_graphql
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "MainLayout_OrganizationSelector_viewer",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": "organizations",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"kind": "Literal",
|
||||||
|
"name": "orderBy",
|
||||||
|
"value": {
|
||||||
|
"direction": "ASC",
|
||||||
|
"field": "NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concreteType": "OrganizationConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "__MainLayout_OrganizationSelector_organizations_connection",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "OrganizationEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Organization",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "name",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "logoUrl",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "PageInfo",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "pageInfo",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasNextPage",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "endCursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": "__MainLayout_OrganizationSelector_organizations_connection(orderBy:{\"direction\":\"ASC\",\"field\":\"NAME\"})"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Viewer",
|
||||||
|
"abstractKey": null
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "0dc2841aeeb6ba5291cb45d8644ec4af";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -9,18 +9,13 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
IconPlusLarge,
|
IconPlusLarge,
|
||||||
ActionDropdown,
|
|
||||||
DropdownItem,
|
|
||||||
IconTrashCan,
|
|
||||||
} from "@probo/ui";
|
} from "@probo/ui";
|
||||||
import { usePageTitle } from "@probo/hooks";
|
import { usePageTitle } from "@probo/hooks";
|
||||||
import { useDeleteOrganizationMutation } from "../hooks/graph/OrganizationGraph";
|
|
||||||
import { DeleteOrganizationDialog } from "../components/organizations/DeleteOrganizationDialog";
|
|
||||||
|
|
||||||
const OrganizationsPageQuery = graphql`
|
const OrganizationsPageQuery = graphql`
|
||||||
query OrganizationsPageQuery {
|
query OrganizationsPageQuery {
|
||||||
viewer {
|
viewer {
|
||||||
organizations(first: 25) @connection(key: "OrganizationsPage_organizations") {
|
organizations(first: 1000, orderBy: {field: NAME, direction: ASC}) @connection(key: "OrganizationsPage_organizations") {
|
||||||
__id
|
__id
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
@@ -67,7 +62,6 @@ export default function OrganizationsPage() {
|
|||||||
<OrganizationCard
|
<OrganizationCard
|
||||||
key={organization.id}
|
key={organization.id}
|
||||||
organization={organization}
|
organization={organization}
|
||||||
connectionId={data.viewer.organizations.__id}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<Card padded>
|
<Card padded>
|
||||||
@@ -98,23 +92,10 @@ type OrganizationCardProps = {
|
|||||||
name: string;
|
name: string;
|
||||||
logoUrl: string | null | undefined;
|
logoUrl: string | null | undefined;
|
||||||
};
|
};
|
||||||
connectionId: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function OrganizationCard({ organization, connectionId }: OrganizationCardProps) {
|
function OrganizationCard({ organization }: OrganizationCardProps) {
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const [deleteOrganization, isDeleting] = useDeleteOrganizationMutation();
|
|
||||||
|
|
||||||
const handleDelete = () => {
|
|
||||||
return deleteOrganization({
|
|
||||||
variables: {
|
|
||||||
input: {
|
|
||||||
organizationId: organization.id,
|
|
||||||
},
|
|
||||||
connections: [connectionId],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card padded className="w-full">
|
<Card padded className="w-full">
|
||||||
@@ -136,21 +117,6 @@ function OrganizationCard({ organization, connectionId }: OrganizationCardProps)
|
|||||||
{__("Select")}
|
{__("Select")}
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<DeleteOrganizationDialog
|
|
||||||
organizationName={organization.name}
|
|
||||||
onConfirm={handleDelete}
|
|
||||||
isDeleting={isDeleting}
|
|
||||||
>
|
|
||||||
<ActionDropdown>
|
|
||||||
<DropdownItem
|
|
||||||
variant="danger"
|
|
||||||
icon={IconTrashCan}
|
|
||||||
disabled={isDeleting}
|
|
||||||
>
|
|
||||||
{__("Delete organization")}
|
|
||||||
</DropdownItem>
|
|
||||||
</ActionDropdown>
|
|
||||||
</DeleteOrganizationDialog>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<70d28036f17c3b03dcfecce6abd5b476>>
|
* @generated SignedSource<<84d0e43eced78862d1c82603e9c332e8>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -31,13 +31,21 @@ export type OrganizationsPageQuery = {
|
|||||||
|
|
||||||
const node: ConcreteRequest = (function(){
|
const node: ConcreteRequest = (function(){
|
||||||
var v0 = {
|
var v0 = {
|
||||||
|
"kind": "Literal",
|
||||||
|
"name": "orderBy",
|
||||||
|
"value": {
|
||||||
|
"direction": "ASC",
|
||||||
|
"field": "NAME"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v1 = {
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v1 = [
|
v2 = [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -54,7 +62,7 @@ v1 = [
|
|||||||
"name": "node",
|
"name": "node",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v0/*: any*/),
|
(v1/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -127,12 +135,13 @@ v1 = [
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
v2 = [
|
v3 = [
|
||||||
{
|
{
|
||||||
"kind": "Literal",
|
"kind": "Literal",
|
||||||
"name": "first",
|
"name": "first",
|
||||||
"value": 25
|
"value": 1000
|
||||||
}
|
},
|
||||||
|
(v0/*: any*/)
|
||||||
];
|
];
|
||||||
return {
|
return {
|
||||||
"fragment": {
|
"fragment": {
|
||||||
@@ -151,13 +160,15 @@ return {
|
|||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": "organizations",
|
"alias": "organizations",
|
||||||
"args": null,
|
"args": [
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
"concreteType": "OrganizationConnection",
|
"concreteType": "OrganizationConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "__OrganizationsPage_organizations_connection",
|
"name": "__OrganizationsPage_organizations_connection",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": (v1/*: any*/),
|
"selections": (v2/*: any*/),
|
||||||
"storageKey": null
|
"storageKey": "__OrganizationsPage_organizations_connection(orderBy:{\"direction\":\"ASC\",\"field\":\"NAME\"})"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -182,31 +193,33 @@ return {
|
|||||||
"selections": [
|
"selections": [
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v2/*: any*/),
|
"args": (v3/*: any*/),
|
||||||
"concreteType": "OrganizationConnection",
|
"concreteType": "OrganizationConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "organizations",
|
"name": "organizations",
|
||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": (v1/*: any*/),
|
"selections": (v2/*: any*/),
|
||||||
"storageKey": "organizations(first:25)"
|
"storageKey": "organizations(first:1000,orderBy:{\"direction\":\"ASC\",\"field\":\"NAME\"})"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v2/*: any*/),
|
"args": (v3/*: any*/),
|
||||||
"filters": null,
|
"filters": [
|
||||||
|
"orderBy"
|
||||||
|
],
|
||||||
"handle": "connection",
|
"handle": "connection",
|
||||||
"key": "OrganizationsPage_organizations",
|
"key": "OrganizationsPage_organizations",
|
||||||
"kind": "LinkedHandle",
|
"kind": "LinkedHandle",
|
||||||
"name": "organizations"
|
"name": "organizations"
|
||||||
},
|
},
|
||||||
(v0/*: any*/)
|
(v1/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "ddaafef96749a932a0cee5286a3c2bbd",
|
"cacheID": "1735764e6816660969c5f96922320ac5",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"connection": [
|
"connection": [
|
||||||
@@ -223,11 +236,11 @@ return {
|
|||||||
},
|
},
|
||||||
"name": "OrganizationsPageQuery",
|
"name": "OrganizationsPageQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query OrganizationsPageQuery {\n viewer {\n organizations(first: 25) {\n edges {\n node {\n id\n name\n logoUrl\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n id\n }\n}\n"
|
"text": "query OrganizationsPageQuery {\n viewer {\n organizations(first: 1000, orderBy: {field: NAME, direction: ASC}) {\n edges {\n node {\n id\n name\n logoUrl\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n id\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "122ab4331082ffe892fa7fe48692d961";
|
(node as any).hash = "6fde39384e4678f88f17c34bbd30e684";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -57,7 +57,11 @@ export default function NewOrganizationPage() {
|
|||||||
connections: [
|
connections: [
|
||||||
ConnectionHandler.getConnectionID(
|
ConnectionHandler.getConnectionID(
|
||||||
data.viewer.id,
|
data.viewer.id,
|
||||||
"NewOrganizationPageQuery"
|
"OrganizationsPage_organizations"
|
||||||
|
),
|
||||||
|
ConnectionHandler.getConnectionID(
|
||||||
|
data.viewer.id,
|
||||||
|
"MainLayout_OrganizationSelector_organizations"
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,8 +41,12 @@ type (
|
|||||||
|
|
||||||
func (o Organization) CursorKey(orderBy OrganizationOrderField) page.CursorKey {
|
func (o Organization) CursorKey(orderBy OrganizationOrderField) page.CursorKey {
|
||||||
switch orderBy {
|
switch orderBy {
|
||||||
|
case OrganizationOrderFieldName:
|
||||||
|
return page.NewCursorKey(o.ID, o.Name)
|
||||||
case OrganizationOrderFieldCreatedAt:
|
case OrganizationOrderFieldCreatedAt:
|
||||||
return page.NewCursorKey(o.ID, o.CreatedAt)
|
return page.NewCursorKey(o.ID, o.CreatedAt)
|
||||||
|
case OrganizationOrderFieldUpdatedAt:
|
||||||
|
return page.NewCursorKey(o.ID, o.UpdatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
|
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
|
||||||
@@ -90,6 +94,57 @@ LIMIT 1;
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tenant id scope is not applied in this functions because we want to access all user's organizations.
|
||||||
|
func (o *Organizations) ListForUserID(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
userID gid.GID,
|
||||||
|
cursor *page.Cursor[OrganizationOrderField],
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
WITH user_org AS (
|
||||||
|
SELECT
|
||||||
|
organization_id
|
||||||
|
FROM
|
||||||
|
users_organizations
|
||||||
|
WHERE
|
||||||
|
user_id = @user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
tenant_id,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
logo_object_key,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
FROM
|
||||||
|
organizations
|
||||||
|
INNER JOIN
|
||||||
|
user_org ON organizations.id = user_org.organization_id
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, cursor.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{"user_id": userID}
|
||||||
|
maps.Copy(args, cursor.SQLArguments())
|
||||||
|
|
||||||
|
rows, err := conn.Query(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot query organizations: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
organizations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Organization])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot collect organizations: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
*o = organizations
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Organization) Insert(
|
func (o *Organization) Insert(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
conn pg.Conn,
|
conn pg.Conn,
|
||||||
|
|||||||
@@ -4870,25 +4870,26 @@ func (r *vendorServiceResolver) Vendor(ctx context.Context, obj *types.VendorSer
|
|||||||
func (r *viewerResolver) Organizations(ctx context.Context, obj *types.Viewer, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrganizationOrder, filter *types.OrganizationFilter) (*types.OrganizationConnection, error) {
|
func (r *viewerResolver) Organizations(ctx context.Context, obj *types.Viewer, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrganizationOrder, filter *types.OrganizationFilter) (*types.OrganizationConnection, error) {
|
||||||
user := UserFromContext(ctx)
|
user := UserFromContext(ctx)
|
||||||
|
|
||||||
// For now, we're not using cursor pagination since we're loading all organizations
|
pageOrderBy := page.OrderBy[coredata.OrganizationOrderField]{
|
||||||
organizations, err := r.usrmgrSvc.ListOrganizationsForUserID(ctx, user.ID)
|
Field: coredata.OrganizationOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
if orderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.OrganizationOrderField]{
|
||||||
|
Field: orderBy.Field,
|
||||||
|
Direction: orderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
|
||||||
|
organizations, err := r.usrmgrSvc.ListOrganizationsForUserIDPaginated(ctx, user.ID, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("failed to list organizations for user: %w", err))
|
panic(fmt.Errorf("failed to list organizations for user: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
var edges []*types.OrganizationEdge
|
page := page.NewPage(organizations, cursor)
|
||||||
for _, organization := range organizations {
|
|
||||||
edges = append(edges, types.NewOrganizationEdge(organization, coredata.OrganizationOrderFieldCreatedAt))
|
|
||||||
}
|
|
||||||
|
|
||||||
// The simple implementation doesn't handle pagination yet
|
return types.NewOrganizationConnection(page), nil
|
||||||
return &types.OrganizationConnection{
|
|
||||||
Edges: edges,
|
|
||||||
PageInfo: &types.PageInfo{
|
|
||||||
HasNextPage: false,
|
|
||||||
HasPreviousPage: false,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asset returns schema.AssetResolver implementation.
|
// Asset returns schema.AssetResolver implementation.
|
||||||
|
|||||||
@@ -515,6 +515,33 @@ func (s Service) ListOrganizationsForUserID(
|
|||||||
return organizations, nil
|
return organizations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tenant id scope is not applied in this functions because we want to access all user's organizations.
|
||||||
|
func (s Service) ListOrganizationsForUserIDPaginated(
|
||||||
|
ctx context.Context,
|
||||||
|
userID gid.GID,
|
||||||
|
cursor *page.Cursor[coredata.OrganizationOrderField],
|
||||||
|
) (coredata.Organizations, error) {
|
||||||
|
organizations := coredata.Organizations{}
|
||||||
|
|
||||||
|
err := s.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
err := organizations.ListForUserID(ctx, conn, userID, cursor)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot list user organizations: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return organizations, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s Service) ListTenantsForUserID(
|
func (s Service) ListTenantsForUserID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
userID gid.GID,
|
userID gid.GID,
|
||||||
|
|||||||
Reference in New Issue
Block a user