feat: create dashboards with graphql

This commit is contained in:
Vyacheslav Matyukhin 2022-04-20 01:29:12 +04:00
parent 4a28c51169
commit 4397a310fe
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C
11 changed files with 124 additions and 79 deletions

View File

@ -1,3 +1,14 @@
input CreateDashboardInput {
creator: String
description: String
ids: [ID!]!
title: String!
}
type CreateDashboardResult {
dashboard: Dashboard!
}
type Dashboard {
creator: String!
description: String!
@ -9,6 +20,10 @@ type Dashboard {
"""Date serialized as the Unix timestamp."""
scalar Date
type Mutation {
createDashboard(input: CreateDashboardInput!): CreateDashboardResult!
}
type PageInfo {
endCursor: String
hasNextPage: Boolean!

View File

@ -15,7 +15,7 @@ const migrate = async () => {
FantasySCOTUS: "fantasyscotus",
Foretold: "foretold",
"GiveWell/OpenPhilanthropy": "givewellopenphil",
"Good Judgment": "goodjudgement",
"Good Judgment": "goodjudgment",
"Good Judgment Open": "goodjudgmentopen",
Infer: "infer",
Kalshi: "kalshi",

View File

@ -37,3 +37,4 @@ builder.scalarType("Date", {
});
builder.queryType({});
builder.mutationType({});

View File

@ -1,6 +1,7 @@
import { Dashboard } from "@prisma/client";
import { prisma } from "../../backend/database/prisma";
import { hash } from "../../backend/utils/hash";
import { builder } from "../builder";
import { QuestionObj } from "./questions";
@ -40,3 +41,49 @@ builder.queryField("dashboard", (t) =>
},
})
);
const CreateDashboardResult = builder
.objectRef<{ dashboard: Dashboard }>("CreateDashboardResult")
.implement({
fields: (t) => ({
dashboard: t.field({
type: DashboardObj,
resolve: (parent) => parent.dashboard,
}),
}),
});
const CreateDashboardInput = builder.inputType("CreateDashboardInput", {
fields: (t) => ({
title: t.string({ required: true }),
description: t.string(),
creator: t.string(),
ids: t.idList({ required: true }),
}),
});
builder.mutationField("createDashboard", (t) =>
t.field({
type: CreateDashboardResult,
args: {
input: t.arg({ type: CreateDashboardInput, required: true }),
},
resolve: async (parent, args) => {
const id = hash(JSON.stringify(args.input.ids));
const dashboard = await prisma.dashboard.create({
data: {
id,
title: args.input.title,
description: args.input.description || "",
creator: args.input.creator || "",
contents: args.input.ids,
extra: [],
timestamp: new Date(),
},
});
return {
dashboard,
};
},
})
);

View File

@ -27,7 +27,7 @@ builder.queryField("searchQuestions", (t) =>
const forecastsThreshold = input.forecastsThreshold;
const starsThreshold = input.starsThreshold;
const platformsIncludeGuesstimate =
input.forecastingPlatforms.includes("guesstimate") &&
input.forecastingPlatforms?.includes("guesstimate") &&
starsThreshold <= 1;
// preparation

View File

@ -14,6 +14,18 @@ export type Scalars = {
Date: any;
};
export type CreateDashboardInput = {
creator?: InputMaybe<Scalars['String']>;
description?: InputMaybe<Scalars['String']>;
ids: Array<Scalars['ID']>;
title: Scalars['String'];
};
export type CreateDashboardResult = {
__typename?: 'CreateDashboardResult';
dashboard: Dashboard;
};
export type Dashboard = {
__typename?: 'Dashboard';
creator: Scalars['String'];
@ -23,6 +35,16 @@ export type Dashboard = {
title: Scalars['String'];
};
export type Mutation = {
__typename?: 'Mutation';
createDashboard: CreateDashboardResult;
};
export type MutationCreateDashboardArgs = {
input: CreateDashboardInput;
};
export type PageInfo = {
__typename?: 'PageInfo';
endCursor?: Maybe<Scalars['String']>;

View File

@ -1,39 +0,0 @@
import { NextApiRequest, NextApiResponse } from "next/types";
import { pgInsertIntoDashboard } from "../../backend/database/pg-wrapper";
import { hash } from "../../backend/utils/hash";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "POST") {
res.status(400).send("Expected POST request");
return;
}
let body = req.body;
console.log(body);
try {
let id = hash(JSON.stringify(body.ids));
let pgResponse = await pgInsertIntoDashboard({
datum: {
id: id,
title: body.title || "",
description: body.description || "",
contents: body.ids,
creator: body.creator || "",
extra: [],
},
});
res.status(200).send({
dashboardId: id,
pgResponse: pgResponse,
});
} catch (error) {
res.status(400).send({
id: null,
pgResponse: JSON.stringify(error),
});
}
}

View File

@ -1,24 +1,33 @@
import axios from "axios";
import { NextPage } from "next";
import { useRouter } from "next/router";
import { useMutation } from "urql";
import { CreateDashboardDocument } from "../../web/dashboards/queries.generated";
import { DashboardCreator } from "../../web/display/DashboardCreator";
import { Layout } from "../../web/display/Layout";
import { LineHeader } from "../../web/display/LineHeader";
const DashboardsPage: NextPage = () => {
const router = useRouter();
const [createDashboardResult, createDashboard] = useMutation(
CreateDashboardDocument
);
const handleSubmit = async (data) => {
// Send to server to create
// Get back the id
let response = await axios({
url: "/api/create-dashboard-from-ids",
method: "POST",
headers: { "Content-Type": "application/json" },
data: JSON.stringify(data),
}).then((res) => res.data);
await router.push(`/dashboards/view/${response.dashboardId}`);
const handleSubmit = async (data: any) => {
await createDashboard({
input: {
title: data.title,
description: data.description,
creator: data.creator,
ids: data.ids,
},
});
console.log(createDashboardResult);
const dashboardId = createDashboardResult?.data?.result?.dashboard?.id;
if (!dashboardId) {
throw new Error("Couldn't create a dashboard"); // TODO - toaster
}
await router.push(`/dashboards/view/${dashboardId}`);
};
return (

View File

@ -11,5 +11,13 @@ export type DashboardByIdQueryVariables = Types.Exact<{
export type DashboardByIdQuery = { __typename?: 'Query', result: { __typename?: 'Dashboard', id: string, title: string, description: string, creator: string, questions: Array<{ __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: any, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null } }> } };
export type CreateDashboardMutationVariables = Types.Exact<{
input: Types.CreateDashboardInput;
}>;
export type CreateDashboardMutation = { __typename?: 'Mutation', result: { __typename?: 'CreateDashboardResult', dashboard: { __typename?: 'Dashboard', id: string, title: string, description: string, creator: string, questions: Array<{ __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: any, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null } }> } } };
export const DashboardFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Dashboard"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Dashboard"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"creator"}},{"kind":"Field","name":{"kind":"Name","value":"questions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Question"}}]}}]}},...QuestionFragmentDoc.definitions]} as unknown as DocumentNode<DashboardFragment, unknown>;
export const DashboardByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DashboardById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"dashboard"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Dashboard"}}]}}]}},...DashboardFragmentDoc.definitions]} as unknown as DocumentNode<DashboardByIdQuery, DashboardByIdQueryVariables>;
export const DashboardByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DashboardById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"dashboard"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Dashboard"}}]}}]}},...DashboardFragmentDoc.definitions]} as unknown as DocumentNode<DashboardByIdQuery, DashboardByIdQueryVariables>;
export const CreateDashboardDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateDashboard"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateDashboardInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"createDashboard"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"dashboard"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Dashboard"}}]}}]}}]}},...DashboardFragmentDoc.definitions]} as unknown as DocumentNode<CreateDashboardMutation, CreateDashboardMutationVariables>;

View File

@ -13,3 +13,11 @@ query DashboardById($id: ID!) {
...Dashboard
}
}
mutation CreateDashboard($input: CreateDashboardInput!) {
result: createDashboard(input: $input) {
dashboard {
...Dashboard
}
}
}

View File

@ -1,26 +0,0 @@
import axios from "axios";
export async function createDashboard(payload) {
let data = { dashboardId: null };
try {
let { title, description, ids, creator, extra } = payload;
console.log(payload);
let response = await axios({
url: "/api/create-dashboard-from-ids",
method: "post",
data: {
title: title || "",
description: description || "",
ids: ids,
creator: creator || "",
extra: [],
},
});
data = response.data;
console.log(data);
} catch (error) {
console.log(error);
} finally {
return data;
}
}