diff --git a/core/app/c/[communitySlug]/pubs/[pubId]/page.tsx b/core/app/c/[communitySlug]/pubs/[pubId]/page.tsx
index 01b003a0f9..0641e404f1 100644
--- a/core/app/c/[communitySlug]/pubs/[pubId]/page.tsx
+++ b/core/app/c/[communitySlug]/pubs/[pubId]/page.tsx
@@ -1,25 +1,29 @@
-import { PubField, PubFieldSchema, PubValue, Prisma } from "@prisma/client";
+import { Prisma, PubField, PubFieldSchema, PubValue } from "@prisma/client";
import { AnySchema, JSONSchemaType } from "ajv";
import Link from "next/link";
import {
- Button,
Avatar,
AvatarFallback,
AvatarImage,
- Card,
- CardTitle,
+ Button,
CardContent,
CardHeader,
+ CardTitle,
+ HoverCard,
+ HoverCardContent,
+ HoverCardTrigger,
Separator,
} from "ui";
+
import IntegrationActions from "~/app/components/IntegrationActions";
import { PubTitle } from "~/app/components/PubTitle";
import { getLoginData } from "~/lib/auth/loginData";
+import cn from "~/lib/cn";
+import { FileUpload } from "~/lib/fields/fileUpload";
import { getPubUsers } from "~/lib/permissions";
import { createToken } from "~/lib/server/token";
import { pubInclude } from "~/lib/types";
import prisma from "~/prisma/db";
-import cn from "~/lib/cn";
const getPub = async (pubId: string) => {
return await prisma.pub.findUnique({
@@ -37,8 +41,43 @@ interface PubValueWithFieldAndSchema extends PubValue {
field: PubFieldWithValue;
}
+function FileUploadPreview({ files }: { files: FileUpload }) {
+ return (
+
+ {files.map((file) => {
+ return (
+ -
+
+
+
+
+
+
+ {file.fileName}
+
+
+ The file is {file.fileSize} bytes in size. Its
+ MIME type is {file.fileType}.
+
+
+
+
+
+ );
+ })}
+
+ );
+}
+
function recursivelyGetScalarFields(schema: JSONSchemaType, value: Prisma.JsonValue) {
const fields: any[] = [];
+ if (schema.$id === "pubpub:fileUpload") {
+ return ;
+ }
// TODO: get schema IDs and render specific stuff -- e.g. file upload, confidence intervals
if (!schema.properties) {
switch (schema.type) {
diff --git a/core/lib/fields/fileUpload.ts b/core/lib/fields/fileUpload.ts
new file mode 100644
index 0000000000..eaac7ab6a3
--- /dev/null
+++ b/core/lib/fields/fileUpload.ts
@@ -0,0 +1,47 @@
+import { JSONSchemaType } from "ajv";
+
+export type FileUploadFile = {
+ fileName: string;
+ fileSource: string;
+ fileType: string;
+ fileSize: number;
+ fileMeta: object;
+ fileUploadUrl: string;
+ filePreview: string;
+};
+export type FileUpload = FileUploadFile[];
+
+export const FileUpload = {
+ $id: "pubpub:fileUpload",
+ title: "Upload Files",
+ type: "array",
+ items: {
+ type: "object",
+ properties: {
+ fileName: {
+ type: "string",
+ },
+ fileSource: {
+ type: "string",
+ },
+ fileType: {
+ type: "string",
+ },
+ fileSize: {
+ type: "number",
+ },
+ fileMeta: {
+ type: "object",
+ },
+ fileUploadUrl: {
+ type: "string",
+ format: "uri",
+ },
+ filePreview: {
+ type: "string",
+ format: "uri",
+ },
+ },
+ },
+} as unknown as JSONSchemaType;
+
diff --git a/core/prisma/exampleCommunitySeeds/unjournal.ts b/core/prisma/exampleCommunitySeeds/unjournal.ts
index 43d856205d..348a243776 100644
--- a/core/prisma/exampleCommunitySeeds/unjournal.ts
+++ b/core/prisma/exampleCommunitySeeds/unjournal.ts
@@ -1,6 +1,7 @@
import { PrismaClient } from "@prisma/client";
import { v4 as uuidv4 } from "uuid";
import { faker } from "@faker-js/faker";
+import { FileUpload } from "../../lib/fields/fileUpload";
export const unJournalId = "03e7a5fd-bdca-4682-9221-3a69992c1f3b";
@@ -258,39 +259,7 @@ export default async function main(prisma: PrismaClient, communityUUID: string)
data: {
name: "uploadFile",
namespace: "pubpub",
- schema: {
- $id: "pubpub:fileUpload",
- title: "Upload Files",
- type: "array",
- items: {
- type: "object",
- properties: {
- fileName: {
- type: "string",
- },
- fileSource: {
- type: "string",
- },
- fileType: {
- type: "string",
- },
- fileSize: {
- type: "number",
- },
- fileMeta: {
- type: "object",
- },
- fileUploadUrl: {
- type: "string",
- format: "uri",
- },
- filePreview: {
- type: "string",
- format: "uri",
- },
- },
- },
- },
+ schema: FileUpload,
},
});
diff --git a/integrations/evaluations/app/actions/evaluate/evaluate.tsx b/integrations/evaluations/app/actions/evaluate/evaluate.tsx
index 856448eb97..29a8b7130a 100644
--- a/integrations/evaluations/app/actions/evaluate/evaluate.tsx
+++ b/integrations/evaluations/app/actions/evaluate/evaluate.tsx
@@ -8,7 +8,6 @@ import { fullFormats } from "ajv-formats/dist/formats";
import { useEffect, useMemo } from "react";
import { useForm } from "react-hook-form";
import { Button, Form, Icon, useLocalStorage, useToast } from "ui";
-import { cn } from "utils";
import { Process } from "~/lib/components/Process";
import { Research } from "~/lib/components/Research";
import { InstanceConfig } from "~/lib/types";
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 5142378b40..b7f70258d1 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -18,6 +18,7 @@
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
+ "@radix-ui/react-hover-card": "^1.0.7",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.6",
diff --git a/packages/ui/src/customRenderers/fileUpload/fileUpload.tsx b/packages/ui/src/customRenderers/fileUpload/fileUpload.tsx
index 1b73941489..76be614fca 100644
--- a/packages/ui/src/customRenderers/fileUpload/fileUpload.tsx
+++ b/packages/ui/src/customRenderers/fileUpload/fileUpload.tsx
@@ -9,7 +9,6 @@ import { Dashboard } from "@uppy/react";
import "@uppy/core/dist/style.min.css";
import "@uppy/dashboard/dist/style.min.css";
-import { cn } from "utils";
import AwsS3 from "@uppy/aws-s3";
const uppy = new Uppy().use(AwsS3);
@@ -19,15 +18,6 @@ type FileUploadProps = {
onUpdateFiles: Function;
};
-type UploadedFile = {
- fileName: String;
- fileSource?: String;
- fileType?: String;
- fileSize?: Number;
- fileMeta?: Object;
- filePreview?: String;
- fileUploadUrl: String;
-};
const FileUpload = forwardRef(function FileUpload(props: FileUploadProps, ref) {
useEffect(() => {
uppy.on("complete", () => {
diff --git a/packages/ui/src/hover-card.tsx b/packages/ui/src/hover-card.tsx
new file mode 100644
index 0000000000..d9b0522668
--- /dev/null
+++ b/packages/ui/src/hover-card.tsx
@@ -0,0 +1,29 @@
+"use client";
+
+import * as React from "react";
+import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
+
+import { cn } from "utils";
+
+const HoverCard = HoverCardPrimitive.Root;
+
+const HoverCardTrigger = HoverCardPrimitive.Trigger;
+
+const HoverCardContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
+
+));
+HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
+
+export { HoverCard, HoverCardTrigger, HoverCardContent };
diff --git a/packages/ui/src/index.tsx b/packages/ui/src/index.tsx
index 63be3f77b7..e314adb011 100644
--- a/packages/ui/src/index.tsx
+++ b/packages/ui/src/index.tsx
@@ -13,6 +13,7 @@ export * from "./checkbox";
export * from "./dialog";
export * from "./dropdown-menu";
export * from "./form";
+export * from "./hover-card";
export * from "./input";
export * from "./label";
export * from "./popover";
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6017c4010f..4062335a3f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -446,6 +446,9 @@ importers:
'@radix-ui/react-dropdown-menu':
specifier: ^2.0.5
version: 2.0.5(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-hover-card':
+ specifier: ^1.0.7
+ version: 1.0.7(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-icons':
specifier: ^1.3.0
version: 1.3.0(react@18.2.0)
@@ -3378,6 +3381,30 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
+ /@radix-ui/react-dismissable-layer@1.0.5(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.22.10
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.12)(react@18.2.0)
+ '@types/react': 18.2.12
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@radix-ui/react-dropdown-menu@2.0.5(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-xdOrZzOTocqqkCkYo8yRPCib5OkTkqN7lqNCdxwPOdE466DOaNl4N8PkUIlsXthQvW5Wwkd+aEmWpfWlBoDPEw==}
peerDependencies:
@@ -3440,6 +3467,34 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
+ /@radix-ui/react-hover-card@1.0.7(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.22.10
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-popper': 1.1.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-portal': 1.0.4(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@types/react': 18.2.12
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@radix-ui/react-icons@1.3.0(react@18.2.0):
resolution: {integrity: sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==}
peerDependencies:
@@ -3583,6 +3638,35 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
+ /@radix-ui/react-popper@1.1.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.22.10
+ '@floating-ui/react-dom': 2.0.1(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-arrow': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.12)(react@18.2.0)
+ '@radix-ui/rect': 1.0.1
+ '@types/react': 18.2.12
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@radix-ui/react-portal@1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==}
peerDependencies:
@@ -3603,6 +3687,26 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
+ /@radix-ui/react-portal@1.0.4(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.22.10
+ '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.12
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@radix-ui/react-presence@1.0.1(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
peerDependencies: