Skip to content

Commit

Permalink
File upload
Browse files Browse the repository at this point in the history
  • Loading branch information
willnode committed Jul 23, 2024
1 parent ba92278 commit 441fc0c
Show file tree
Hide file tree
Showing 23 changed files with 376 additions and 73 deletions.
2 changes: 1 addition & 1 deletion src/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as cookie from "hono/cookie";
import { ulid } from "ulid";
import bcrypt from "bcryptjs";

const authSecret: string = process.env.AUTH_SECRET || "secret";
const authSecret: string = import.meta.env.AUTH_SECRET || "secret";

const loginSchema = z.object({
email: z.string().email(),
Expand Down
56 changes: 56 additions & 0 deletions src/api/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Hono } from "hono";
import { rError, rOK } from "./helper";
import { unflatten } from "flat";
import { Entry, File, Form } from "@/db/schema";
import db from "@/lib/db";
import { eq } from "drizzle-orm";
import { validator } from "hono/validator";
import { ulid } from "ulid";
import query from "../lib/query";
import { getSession, getTeam } from "@/lib/auth";
import { handleFormUpload } from "@/components/model";

const form = new Hono()
.get(
"/get",
async (c) => {
const team = await getTeam(c.req.raw);
if (!team) {
return rError(c, "Unauthenticated");
}
const r = await query.getViewComponentListByTeamId(team);
return rOK(c, r);
},
)
.post(
"/upload",
validator("form", (v) => v),
async (c) => {

const team = await getTeam(c.req.raw);
if (!team) {
return rError(c, "Unauthenticated");
}
const values = await handleFormUpload(c, null, team) as any;
let id = values.file;
if (typeof id !== 'string') {
return rError(c, "Emm no shit");
}
return rOK(c, id);
},
)
.post(
"/delete/:id",
async (c) => {
let id = c.req.param("id");
let r = await db
.delete(File)
.where(eq(File.id, id));
if (r[0].affectedRows == 0) {
return rError(c, "Emm no shit");
}
return rOK(c);
},
)

export default form;
4 changes: 2 additions & 2 deletions src/api/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { eq } from "drizzle-orm";
import { validator } from "hono/validator";
import { ulid } from "ulid";
import query from "../lib/query";
import { getTeam } from "@/lib/auth";
import { getSession, getTeam } from "@/lib/auth";
import { handleFormUpload } from "@/components/model";

const form = new Hono()
Expand Down Expand Up @@ -61,7 +61,7 @@ const form = new Hono()
return rError(c, "not found");
}

const data: any = await handleFormUpload(await c.req.formData(), formId, form.teamId);
const data: any = await handleFormUpload(c, formId, form.teamId);
const id = ulid();
await db.insert(Entry).values({
formId,
Expand Down
2 changes: 2 additions & 0 deletions src/api/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { ZodError } from "zod";
import { rError, rOK } from "./helper";
import form from "./form";
import view from "./view";
import file from "./file";
import viewComponent from "./view-component";

const app = new Hono()
.use(logger())
.route("/api/auth", auth)
.route("/api/form", form)
.route("/api/view", view)
.route("/api/file", file)
.route("/api/view-component", viewComponent)
.get("/api/health", async (c) => {
return rOK(c);
Expand Down
1 change: 1 addition & 0 deletions src/components/control/File.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default function File({ parentID, form, schema }: ControlProps) {
placeholder={schema.placeholder}
multiple={schema.multiple}
name={name}
id={name}
required={!!schema.required}
/>
</FormItem>
Expand Down
7 changes: 6 additions & 1 deletion src/components/control/FormControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import formSchema from "../editor/form.ts";
import viewSchema from "../editor/view.ts";
import { Button } from "../ui/button.tsx";
import viewComponentSchema from "../editor/viewComponent.ts";
import fileSchema from "../editor/file.ts";

export type FormProps = {
schema: any;
Expand All @@ -21,6 +22,10 @@ export function EditorViewControl(props: Omit<FormProps, "schema">) {
return <FormControl {...props} schema={viewSchema} />;
}

export function EditorFileControl(props: Omit<FormProps, "schema">) {
return <FormControl {...props} schema={fileSchema} />;
}

export function EditorViewComponentControl(props: Omit<FormProps, "schema">) {
return <FormControl {...props} schema={viewComponentSchema} />;
}
Expand All @@ -37,7 +42,7 @@ export function FormControl({ schema, onSubmit, disabled, value }: FormProps) {
<form onSubmit={form.handleSubmit(onSubmit)}>
<fieldset disabled={disabled}>
<Control form={form} parentID="" schema={rSchema} />
<Button className="my-3">Save</Button>
<Button name="formSubmitBtn" className="my-3">Save</Button>
</fieldset>
</form>
</Form>
Expand Down
13 changes: 13 additions & 0 deletions src/components/editor/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@


const fileSchema = {
type: 'group',
children: [{
label: 'File',
id: 'file',
type: 'file',
required: true,
},],
}

export default fileSchema;
19 changes: 18 additions & 1 deletion src/components/editor/puck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ const config: Config = {
components: ['Text', 'Button', 'Card']
}
},
root: {
fields: {
title: {
type: "text",
},
description: {
type: "textarea",
},
thumbnail: {
type: "external",

},
css: {
type: "textarea",
},
}
},
components: {
Box: {
fields: {
Expand Down Expand Up @@ -200,7 +217,7 @@ const config: Config = {

return <div style={css}>{dataMock.map((data: any, i: number) => {
return <React.Fragment key={i}>
<DataContext.Provider value={{...oldData, ...data}}>
<DataContext.Provider value={{ ...oldData, ...data }}>
<DropZone zone="children" />
</DataContext.Provider>
</React.Fragment>
Expand Down
16 changes: 15 additions & 1 deletion src/components/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,18 @@ export function cssToStyle(str: string | undefined) {
obj[_.kebabCase(key)] = value.join(":").trim();
return obj;
}, {})
}
}

export function formatBytes(bytes: number, precision = 1) {
var units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];

bytes = Math.max(bytes, 0);
var pow = Math.floor((bytes ? Math.log(bytes) : 0) / Math.log(1024));
pow = Math.min(pow, units.length - 1);

// Uncomment one of the following alternatives
bytes /= Math.pow(1024, pow);
// bytes /= (1 << (10 * pow));

return bytes.toFixed(precision) + ' ' + units[pow];
}
12 changes: 8 additions & 4 deletions src/components/model.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { Team, File as FileDB } from "@/db/schema";
import { File as FileDB } from "@/db/schema";
import db from "@/lib/db";
import { unflatten } from "flat";
import path from "node:path";
import fsp from "node:fs/promises";
import fs from "node:fs";
import { ulid } from "ulid";
import { extractFormData } from "../components/helper";
import { getApiSession, getSession } from "@/lib/auth";
import type { Context } from "hono";

export async function handleFormUpload(
data: FormData,
formId: string,
c: Context,
formId: string | null,
teamId: string,
) {
const entries = extractFormData(data);
const entries = extractFormData(await c.req.formData());
const authorId = await getApiSession(c)
for (const entry of Object.keys(entries)) {
let v = entries[entry];
if (v instanceof File) {
Expand All @@ -31,6 +34,7 @@ export async function handleFormUpload(

await db.insert(FileDB).values({
formId,
authorId,
path: p,
size: v.size,
teamId,
Expand Down
12 changes: 6 additions & 6 deletions src/db/schema.mysql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ export const ViewComponent = mysqlTable("view_component", {

export const File = mysqlTable("file", {
id: varchar("id", { length: 26 }).primaryKey(),
formId: varchar("form_id", { length: 26 }).references(() => Form.id).notNull(),
authorId: varchar("author_id", { length: 26 }).references(() => User.id).notNull(),
formId: varchar("form_id", { length: 26 }).references(() => Form.id),
authorId: varchar("author_id", { length: 26 }).references(() => User.id),
teamId: varchar("team_id", { length: 26 }).references(() => Team.id).notNull(),
size: int("size"),
type: text("type"),
name: text("name"),
path: text("path"),
size: int("size").notNull(),
type: text("type").notNull(),
name: text("name").notNull(),
path: text("path").notNull(),
created: timestamp("created").defaultNow(),
modified: timestamp("modified").defaultNow(),
});
Expand Down
20 changes: 10 additions & 10 deletions src/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Context } from "hono";
import * as cookie from "hono/cookie";
import query from "./query";

const authSecret: string = process.env.AUTH_SECRET || "secret";
const authSecret: string = import.meta.env.AUTH_SECRET || "secret";
const authCookieName: string = "uid";

// get session under SSR
Expand All @@ -16,18 +16,18 @@ export async function getApiSession(c: Context): Promise<string | null> {
}

export async function getTeam(req: Request) {
try {
const session = await getSession(req);
if (!session) {
return null;
}
let q = await query.getTeamByUser(session);
return q?.id || null;
} catch (error) {
console.error(error);
try {
const session = await getSession(req);
if (!session) {
return null;
}
let q = await query.getTeamByUser(session);
return q?.id || null;
} catch (error) {
console.error(error);
return null;
}
}

export async function setSession(c: Context, id: string) {
await cookie.setSignedCookie(c, authCookieName, id, authSecret, {
Expand Down
11 changes: 5 additions & 6 deletions src/lib/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import {migrate} from 'drizzle-orm/mysql2/migrator';

import * as schema from '@/db/schema';
import mysql from 'mysql2/promise';

const mySqlConfig = {
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'oneform_db',
port: parseInt(process.env.DB_PORT || '3306'),
host: import.meta.env.DB_HOST || 'localhost',
user: import.meta.env.DB_USER || 'root',
password: import.meta.env.DB_PASSWORD || '',
database: import.meta.env.DB_NAME || 'oneform_db',
port: parseInt(import.meta.env.DB_PORT || '3306'),
};

const sql = mysql.createPool(mySqlConfig);
Expand Down
Loading

0 comments on commit 441fc0c

Please sign in to comment.