Skip to content

Commit

Permalink
rewrite SelectOwner, SelectUser, SelectGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
berekuk committed Nov 28, 2024
1 parent 456f3c7 commit 64844e5
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 168 deletions.
24 changes: 24 additions & 0 deletions packages/hub/src/app/api/find-owners/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { NextRequest } from "next/server";
import { z } from "zod";

import { findOwnersForSelect } from "@/server/owners/data";

// We're not calling this as a server actions because it'd be too slow (server actions are sequential).
// TODO: it'd be good to use tRPC for this.
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);

const { search, mode } = z
.object({
search: z.string(),
mode: z.enum(["all", "all-users", "all-groups", "my", "my-groups"]),
})
.parse(Object.fromEntries(searchParams.entries()));

return Response.json(
await findOwnersForSelect({
search,
mode,
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const AddUserToGroupAction: FC<Props> = ({ groupRef, close }) => {
formDataToVariables={(data) => ({
input: {
group: group.slug,
username: data.user.username,
username: data.user.slug,
role: data.role,
},
connections: [
Expand Down
54 changes: 20 additions & 34 deletions packages/hub/src/components/SelectGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,13 @@
"use client";
import { FieldPathByValue, FieldValues } from "react-hook-form";
import { useRelayEnvironment } from "react-relay";
import { fetchQuery, graphql } from "relay-runtime";
import { z } from "zod";

import { SelectFormField } from "@quri/ui";

import {
SelectGroupQuery,
SelectGroupQuery$data,
} from "@/__generated__/SelectGroupQuery.graphql";

const Query = graphql`
query SelectGroupQuery($input: GroupsQueryInput!) {
groups(input: $input) {
edges {
node {
id
slug
}
}
}
}
`;

export type SelectGroupOption =
SelectGroupQuery$data["groups"]["edges"][number]["node"];
export type SelectGroupOption = {
id: string;
slug: string;
};

export function SelectGroup<
TValues extends FieldValues,
Expand All @@ -45,23 +28,26 @@ export function SelectGroup<
required?: boolean;
myOnly?: boolean;
}) {
const environment = useRelayEnvironment();

const loadOptions = async (
inputValue: string
): Promise<SelectGroupOption[]> => {
const result = await fetchQuery<SelectGroupQuery>(environment, Query, {
input: {
slugContains: inputValue,
myOnly,
},
}).toPromise();
const result = await fetch(
`/api/find-owners?${new URLSearchParams({
search: inputValue,
mode: myOnly ? "my-groups" : "all-groups",
})}`
).then((r) => r.json());

if (!result) {
return [];
}
const data = z
.array(
z.object({
id: z.string(),
slug: z.string(),
})
)
.parse(result);

return result.groups.edges.map((edge) => edge.node);
return data;
};

return (
Expand Down
71 changes: 17 additions & 54 deletions packages/hub/src/components/SelectOwner.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,12 @@
"use client";
import { FC } from "react";
import { FieldPathByValue, FieldValues } from "react-hook-form";
import { useRelayEnvironment } from "react-relay";
import { fetchQuery, graphql } from "relay-runtime";
import { z } from "zod";

import { SelectFormField } from "@quri/ui";

import { ownerIcon } from "@/lib/ownerIcon";

import { SelectOwnerQuery } from "@/__generated__/SelectOwnerQuery.graphql";

const Query = graphql`
query SelectOwnerQuery($search: String!, $myOnly: Boolean!) {
me @include(if: $myOnly) {
asUser {
__typename
id
slug
}
}
users(input: { usernameContains: $search }) @skip(if: $myOnly) {
edges {
node {
__typename
id
slug
}
}
}
groups(input: { slugContains: $search, myOnly: $myOnly }) {
edges {
node {
__typename
id
slug
}
}
}
}
`;

// Note: we can't wrap this in a fragment because it's not possible to call `useFragment`
// in SelectFormField callbacks.
export type SelectOwnerOption = {
__typename: "User" | "Group";
id: string;
Expand Down Expand Up @@ -75,29 +40,27 @@ export function SelectOwner<
required?: boolean;
myOnly?: boolean;
}) {
const environment = useRelayEnvironment();

const loadOptions = async (
inputValue: string
): Promise<SelectOwnerOption[]> => {
const result = await fetchQuery<SelectOwnerQuery>(environment, Query, {
search: inputValue,
myOnly,
}).toPromise();
const result = await fetch(
`/api/find-owners?${new URLSearchParams({
search: inputValue,
mode: myOnly ? "my" : "all",
})}`
).then((r) => r.json());

if (!result) {
return [];
}
const data = z
.array(
z.object({
__typename: z.enum(["User", "Group"]),
id: z.string(),
slug: z.string(),
})
)
.parse(result);

const options: SelectOwnerOption[] = [];
if (result.me) {
options.push(result.me.asUser);
}
if (result.users) {
options.push(...(result.users.edges.map((edge) => edge.node) ?? []));
}
options.push(...result.groups.edges.map((edge) => edge.node));
return options;
return data;
};

return (
Expand Down
59 changes: 23 additions & 36 deletions packages/hub/src/components/SelectUser.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,13 @@
"use client";
import { FieldPathByValue, FieldValues } from "react-hook-form";
import { useRelayEnvironment } from "react-relay";
import { fetchQuery, graphql } from "relay-runtime";
import { z } from "zod";

import { SelectFormField } from "@quri/ui";

import {
SelectUserQuery,
SelectUserQuery$data,
} from "@/__generated__/SelectUserQuery.graphql";

const Query = graphql`
query SelectUserQuery($input: UsersQueryInput!) {
users(input: $input) {
edges {
node {
id
username
}
}
}
}
`;

export type SelectUserOption =
SelectUserQuery$data["users"]["edges"][number]["node"];
export type SelectUserOption = {
id: string;
slug: string;
};

export function SelectUser<TValues extends FieldValues>({
name,
Expand All @@ -35,22 +18,26 @@ export function SelectUser<TValues extends FieldValues>({
label?: string;
required?: boolean;
}) {
const environment = useRelayEnvironment();

const loadOptions = async (
inputValue: string
): Promise<SelectUserOption[]> => {
const result = await fetchQuery<SelectUserQuery>(environment, Query, {
input: {
usernameContains: inputValue,
},
}).toPromise();

if (!result) {
return [];
}

return result.users.edges.map((edge) => edge.node);
const result = await fetch(
`/api/find-owners?${new URLSearchParams({
search: inputValue,
mode: "all-users",
})}`
).then((r) => r.json());

const data = z
.array(
z.object({
id: z.string(),
slug: z.string(),
})
)
.parse(result);

return data;
};

return (
Expand All @@ -60,7 +47,7 @@ export function SelectUser<TValues extends FieldValues>({
required={required}
async
loadOptions={loadOptions}
renderOption={(user) => user.username}
renderOption={(user) => user.slug}
/>
);
}
41 changes: 0 additions & 41 deletions packages/hub/src/graphql/queries/users.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/hub/src/graphql/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import "./queries/relativeValuesDefinitions";
import "./queries/runSquiggle";
import "./queries/search";
import "./queries/userByUsername";
import "./queries/users";
import "./mutations/acceptReusableGroupInviteToken";
import "./mutations/adminUpdateModelVersion";
import "./mutations/adminRebuildSearchIndex";
Expand Down
2 changes: 1 addition & 1 deletion packages/hub/src/server/models/actions/moveModelAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const moveModelAction = makeServerAction(
async (input) => {
const session = await getSessionOrRedirect();

let model = await getWriteableModel({
const model = await getWriteableModel({
owner: input.oldOwner,
slug: input.slug,
session,
Expand Down
Loading

0 comments on commit 64844e5

Please sign in to comment.