Skip to content

Commit

Permalink
Merge pull request #3152 from quantified-uncertainty/export-page-lists
Browse files Browse the repository at this point in the history
Show exports on front page
  • Loading branch information
OAGr authored Apr 10, 2024
2 parents e058f4b + 44c61af commit 7d28437
Show file tree
Hide file tree
Showing 24 changed files with 513 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export const SquigglePlayground: React.FC<SquigglePlaygroundProps> = (
const _exports: ModelExport[] = exports.entries().map((e) => ({
variableName: e[0],
variableType: e[1].tag,
title: e[1].title(),
title: e[1].tags.name() ? e[1].tags.name() : e[1].title() || "",
docstring: e[1].context?.docstring() || "",
}));
onExportsChange && onExportsChange(_exports);
Expand Down
2 changes: 2 additions & 0 deletions packages/hub/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"gen:relay": "relay-compiler",
"gen:schema": "tsx ./src/graphql/print-schema.ts",
"gen": "pnpm gen:prisma && pnpm gen:schema && pnpm gen:relay",
"gen:watch": "nodemon --watch src --ext ts,tsx,prisma --exec 'pnpm run gen'",
"build:ts": "pnpm gen && tsc",
"build": "pnpm gen && __NEXT_PRIVATE_PREBUNDLED_REACT=next next build",
"lint": "prettier --check . && next lint",
Expand Down Expand Up @@ -84,6 +85,7 @@
"graphql": "^16.8.1",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"nodemon": "^3.1.0",
"postcss": "^8.4.35",
"prettier": "^3.2.5",
"prisma": "^5.9.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "ModelExport" ADD COLUMN "isCurrent" BOOLEAN NOT NULL DEFAULT false;
UPDATE "ModelExport" SET "isCurrent" = true WHERE "modelRevisionId" IN (SELECT "currentRevisionId" FROM "Model");
1 change: 1 addition & 0 deletions packages/hub/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ model ModelExport {
title String?
docstring String @default("")
variableType String @default("OTHER")
isCurrent Boolean @default(false)
@@unique([modelRevisionId, variableName], name: "uniqueKey")
}
Expand Down
5 changes: 5 additions & 0 deletions packages/hub/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ type Group implements Node & Owner {
inviteForMe: GroupInvite
invites(after: String, before: String, first: Int, last: Int): GroupInviteConnection
memberships(after: String, before: String, first: Int, last: Int): UserGroupMembershipConnection!
modelExports(after: String, before: String, first: Int, last: Int): ModelExport!
models(after: String, before: String, first: Int, last: Int): ModelConnection!
myMembership: UserGroupMembership
reusableInviteToken: String
Expand Down Expand Up @@ -178,7 +179,9 @@ type ModelEdge {
type ModelExport implements Node {
docstring: String!
id: ID!
isCurrent: Boolean!
modelRevision: ModelRevision!
owner: Owner!
title: String
variableName: String!
variableType: String!
Expand All @@ -196,6 +199,7 @@ type ModelExportEdge {

input ModelExportQueryInput {
modelId: String
owner: String
variableName: String
}

Expand Down Expand Up @@ -741,6 +745,7 @@ type User implements Node & Owner {
groups(after: String, before: String, first: Int, last: Int): GroupConnection!
id: ID!
isRoot: Boolean!
modelExports(after: String, before: String, first: Int, last: Int): ModelExportConnection!
models(after: String, before: String, first: Int, last: Int): ModelConnection!
relativeValuesDefinitions(after: String, before: String, first: Int, last: Int): RelativeValuesDefinitionConnection!
slug: String!
Expand Down
6 changes: 6 additions & 0 deletions packages/hub/src/app/FrontPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import { usePageQuery } from "@/relay/usePageQuery";

import { FrontPageDefinitionList } from "./FrontPageDefinitionList";
import { FrontPageGroupList } from "./FrontPageGroupList";
import { FrontPageModelExportList } from "./FrontPageModelExportList";
import { FrontPageModelList } from "./FrontPageModelList";

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

const Query = graphql`
query FrontPageQuery {
...FrontPageModelList
...FrontPageModelExportList
...FrontPageDefinitionList
...FrontPageGroupList
}
Expand All @@ -31,6 +33,7 @@ export const FrontPage: FC<{
<StyledTab.Group>
<StyledTab.List>
<StyledTab name="Models" />
<StyledTab name="Exports" />
<StyledTab name="Definitions" />
<StyledTab name="Groups" />
</StyledTab.List>
Expand All @@ -39,6 +42,9 @@ export const FrontPage: FC<{
<StyledTab.Panel>
<FrontPageModelList dataRef={data} />
</StyledTab.Panel>
<StyledTab.Panel>
<FrontPageModelExportList dataRef={data} />
</StyledTab.Panel>
<StyledTab.Panel>
<FrontPageDefinitionList dataRef={data} />
</StyledTab.Panel>
Expand Down
43 changes: 43 additions & 0 deletions packages/hub/src/app/FrontPageModelExportList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import { FC } from "react";
import { graphql, usePaginationFragment } from "react-relay";

import { ModelExportList } from "@/modelExports/components/ModelExportList";

import { FrontPageModelExportList$key } from "@/__generated__/FrontPageModelExportList.graphql";
import { FrontPageModelExportListPaginationQuery } from "@/__generated__/FrontPageModelExportListPaginationQuery.graphql";

const Fragment = graphql`
fragment FrontPageModelExportList on Query
@argumentDefinitions(
cursor: { type: "String" }
count: { type: "Int", defaultValue: 20 }
)
@refetchable(queryName: "FrontPageModelExportListPaginationQuery") {
modelExports(first: $count, after: $cursor)
@connection(key: "FrontPageModelExportList_modelExports") {
# necessary for Relay
edges {
__typename
}
...ModelExportList
}
}
`;

type Props = {
dataRef: FrontPageModelExportList$key;
};

export const FrontPageModelExportList: FC<Props> = ({ dataRef }) => {
const {
data: { modelExports },
loadNext,
} = usePaginationFragment<
FrontPageModelExportListPaginationQuery,
FrontPageModelExportList$key
>(Fragment, dataRef);

return <ModelExportList connectionRef={modelExports} loadNext={loadNext} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,9 @@ export const EditSquiggleSnippetModel: FC<Props> = ({
playgroundProps.onOpenExport = (sourceId: string, varName?: string) => {
const { owner, slug } = parseSourceId(sourceId);
if (varName) {
router.push(modelExportRoute({ owner, slug, variableName: varName }));
router.push(
modelExportRoute({ owner, modelSlug: slug, variableName: varName })
);
} else {
router.push(modelRoute({ owner, slug }));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function entityNodes(
slug: variable.name,
href: modelExportRoute({
owner: owner.slug,
slug,
modelSlug: slug,
variableName: variable.name,
}),
icon: ShareIcon,
Expand Down
12 changes: 12 additions & 0 deletions packages/hub/src/app/users/[username]/UserLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
newModelRoute,
userDefinitionsRoute,
userGroupsRoute,
userModelExportsRoute,
userRoute,
} from "@/routes";

Expand All @@ -41,6 +42,11 @@ const Query = graphql`
__typename
}
}
modelExports(first: 1) {
edges {
__typename
}
}
relativeValuesDefinitions(first: 1) {
edges {
__typename
Expand Down Expand Up @@ -110,6 +116,12 @@ export const UserLayout: FC<
href={userRoute({ username: user.username })}
/>
) : null}
{isMe || user.modelExports.edges.length ? (
<StyledTabLink
name="Exports"
href={userModelExportsRoute({ username: user.username })}
/>
) : null}
{isMe || user.relativeValuesDefinitions.edges.length ? (
<StyledTabLink
name="Definitions"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { FC } from "react";
import { usePaginationFragment } from "react-relay";
import { graphql } from "relay-runtime";

import { ModelExportList } from "@/modelExports/components/ModelExportList";

import { UserModelExportList$key } from "@/__generated__/UserModelExportList.graphql";

const Fragment = graphql`
fragment UserModelExportList on User
@argumentDefinitions(
cursor: { type: "String" }
count: { type: "Int", defaultValue: 20 }
)
@refetchable(queryName: "UserModelExportListPaginationQuery") {
modelExports(first: $count, after: $cursor)
@connection(key: "UserModelExportList_modelExports") {
edges {
__typename
}
...ModelExportList
}
}
`;

type Props = {
dataRef: UserModelExportList$key;
};

export const UserModelExportList: FC<Props> = ({ dataRef }) => {
const {
data: { modelExports },
loadNext,
} = usePaginationFragment(Fragment, dataRef);

return (
<div>
{modelExports.edges.length ? (
<ModelExportList connectionRef={modelExports} loadNext={loadNext} />
) : (
<div className="text-slate-500">No modelExport to show.</div>
)}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use client";
import { FC } from "react";
import { graphql } from "relay-runtime";

import { extractFromGraphqlErrorUnion } from "@/lib/graphqlHelpers";
import { SerializablePreloadedQuery } from "@/relay/loadPageQuery";
import { usePageQuery } from "@/relay/usePageQuery";

import { UserModelExportList } from "./UserModelExportList";

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

const Query = graphql`
query UserModelExportsPageQuery($username: String!) {
userByUsername(username: $username) {
__typename
... on User {
...UserModelExportList
}
}
}
`;

export const UserModelExportsPage: FC<{
query: SerializablePreloadedQuery<UserModelExportsPageQuery>;
}> = ({ query }) => {
const [{ userByUsername: result }] = usePageQuery(Query, query);

const user = extractFromGraphqlErrorUnion(result, "User");

return <UserModelExportList dataRef={user} />;
};
25 changes: 25 additions & 0 deletions packages/hub/src/app/users/[username]/exports/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Metadata } from "next";

import { loadPageQuery } from "@/relay/loadPageQuery";

import { UserModelExportsPage } from "./UserModelExportsPage";

import QueryNode, {
UserModelExportsPageQuery,
} from "@/__generated__/UserModelExportsPageQuery.graphql";

type Props = {
params: { username: string };
};

export default async function OuterUserModelExportsPage({ params }: Props) {
const query = await loadPageQuery<UserModelExportsPageQuery>(QueryNode, {
username: params.username,
});

return <UserModelExportsPage query={query} />;
}

export function generateMetadata({ params }: Props): Metadata {
return { title: params.username };
}
3 changes: 3 additions & 0 deletions packages/hub/src/graphql/helpers/modelHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ export async function getWriteableModel({
session,
owner,
slug,
include,
}: {
session: Session;
owner: string;
slug: string;
include?: Prisma.ModelInclude;
}): Promise<Model> {
// Note: `findUnique` would be safer, but then we won't be able to use nested queries
const model = await prisma.model.findFirst({
Expand All @@ -63,6 +65,7 @@ export async function getWriteableModel({
],
},
},
include,
});
if (!model) {
// FIXME - this will happen if permissions are not sufficient
Expand Down
13 changes: 12 additions & 1 deletion packages/hub/src/graphql/mutations/updateSquiggleSnippetModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ builder.mutationField("updateSquiggleSnippetModel", (t) =>
const self = await getSelf(session);

const model = await prisma.$transaction(async (tx) => {
if (existingModel.currentRevisionId) {
await tx.modelExport.updateMany({
where: {
modelRevisionId: existingModel.currentRevisionId,
},
data: {
isCurrent: false,
},
});
}

const revision = await tx.modelRevision.create({
data: {
squiggleSnippet: {
Expand Down Expand Up @@ -175,6 +186,7 @@ builder.mutationField("updateSquiggleSnippetModel", (t) =>
variableType,
docstring: docstring ?? undefined,
title: title ?? null,
isCurrent: true,
})
),
},
Expand All @@ -188,7 +200,6 @@ builder.mutationField("updateSquiggleSnippetModel", (t) =>
},
},
});

const model = await tx.model.update({
where: {
id: revision.model.id,
Expand Down
Loading

0 comments on commit 7d28437

Please sign in to comment.