mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
feat(user): add bookmarkedTemplates column to user table and update related API methods
- Introduced a new column `bookmarkedTemplates` to the user table to store user-specific template bookmarks. - Updated API methods to manage bookmarked templates, replacing the deprecated user_template_bookmarks table. - Adjusted queries to retrieve and toggle bookmarks directly from the user record.
This commit is contained in:
1
apps/dokploy/drizzle/0159_polite_puppet_master.sql
Normal file
1
apps/dokploy/drizzle/0159_polite_puppet_master.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "user" ADD COLUMN "bookmarkedTemplates" text[] DEFAULT ARRAY[]::text[];
|
||||
8277
apps/dokploy/drizzle/meta/0159_snapshot.json
Normal file
8277
apps/dokploy/drizzle/meta/0159_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1114,6 +1114,13 @@
|
||||
"when": 1775270343231,
|
||||
"tag": "0158_amused_synch",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 159,
|
||||
"version": "7",
|
||||
"when": 1775274158009,
|
||||
"tag": "0159_polite_puppet_master",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
apiUpdateUser,
|
||||
invitation,
|
||||
member,
|
||||
userTemplateBookmarks,
|
||||
user,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import {
|
||||
hasPermission,
|
||||
@@ -642,12 +642,12 @@ export const userRouter = createTRPCRouter({
|
||||
}),
|
||||
|
||||
getBookmarkedTemplates: protectedProcedure.query(async ({ ctx }) => {
|
||||
const bookmarked = await db.query.userTemplateBookmarks.findMany({
|
||||
where: eq(userTemplateBookmarks.userId, ctx.user.id),
|
||||
orderBy: [asc(userTemplateBookmarks.createdAt)],
|
||||
const result = await db.query.user.findFirst({
|
||||
where: eq(user.id, ctx.user.id),
|
||||
columns: { bookmarkedTemplates: true },
|
||||
});
|
||||
|
||||
return bookmarked.map((b) => b.templateId);
|
||||
return result?.bookmarkedTemplates ?? [];
|
||||
}),
|
||||
|
||||
toggleTemplateBookmark: protectedProcedure
|
||||
@@ -657,24 +657,23 @@ export const userRouter = createTRPCRouter({
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const existing = await db.query.userTemplateBookmarks.findFirst({
|
||||
where: and(
|
||||
eq(userTemplateBookmarks.userId, ctx.user.id),
|
||||
eq(userTemplateBookmarks.templateId, input.templateId),
|
||||
),
|
||||
const result = await db.query.user.findFirst({
|
||||
where: eq(user.id, ctx.user.id),
|
||||
columns: { bookmarkedTemplates: true },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
await db
|
||||
.delete(userTemplateBookmarks)
|
||||
.where(eq(userTemplateBookmarks.id, existing.id));
|
||||
return { isBookmarked: false };
|
||||
}
|
||||
const current = result?.bookmarkedTemplates ?? [];
|
||||
const isBookmarked = current.includes(input.templateId);
|
||||
|
||||
await db.insert(userTemplateBookmarks).values({
|
||||
userId: ctx.user.id,
|
||||
templateId: input.templateId,
|
||||
});
|
||||
return { isBookmarked: true };
|
||||
const updated = isBookmarked
|
||||
? current.filter((id) => id !== input.templateId)
|
||||
: [...current, input.templateId];
|
||||
|
||||
await db
|
||||
.update(user)
|
||||
.set({ bookmarkedTemplates: updated })
|
||||
.where(eq(user.id, ctx.user.id));
|
||||
|
||||
return { isBookmarked: !isBookmarked };
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { relations } from "drizzle-orm";
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import {
|
||||
boolean,
|
||||
integer,
|
||||
pgTable,
|
||||
text,
|
||||
timestamp,
|
||||
unique,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
@@ -67,26 +66,11 @@ export const user = pgTable("user", {
|
||||
stripeSubscriptionId: text("stripeSubscriptionId"),
|
||||
serversQuantity: integer("serversQuantity").notNull().default(0),
|
||||
trustedOrigins: text("trustedOrigins").array(),
|
||||
bookmarkedTemplates: text("bookmarkedTemplates")
|
||||
.array()
|
||||
.default(sql`ARRAY[]::text[]`),
|
||||
});
|
||||
|
||||
export const userTemplateBookmarks = pgTable(
|
||||
"user_template_bookmarks",
|
||||
{
|
||||
id: text("id")
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
templateId: text("templateId").notNull(),
|
||||
createdAt: timestamp("createdAt").notNull().defaultNow(),
|
||||
},
|
||||
(table) => ({
|
||||
uniqueUserTemplate: unique().on(table.userId, table.templateId),
|
||||
}),
|
||||
);
|
||||
|
||||
export const usersRelations = relations(user, ({ one, many }) => ({
|
||||
account: one(account, {
|
||||
fields: [user.id],
|
||||
@@ -98,25 +82,15 @@ export const usersRelations = relations(user, ({ one, many }) => ({
|
||||
ssoProviders: many(ssoProvider),
|
||||
backups: many(backups),
|
||||
schedules: many(schedules),
|
||||
templateBookmarks: many(userTemplateBookmarks),
|
||||
}));
|
||||
|
||||
export const userTemplateBookmarksRelations = relations(
|
||||
userTemplateBookmarks,
|
||||
({ one }) => ({
|
||||
user: one(user, {
|
||||
fields: [userTemplateBookmarks.userId],
|
||||
references: [user.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
const createSchema = createInsertSchema(user, {
|
||||
id: z.string().min(1),
|
||||
isRegistered: z.boolean().optional(),
|
||||
}).omit({
|
||||
role: true,
|
||||
trustedOrigins: true,
|
||||
bookmarkedTemplates: true,
|
||||
isValidEnterpriseLicense: true,
|
||||
});
|
||||
|
||||
|
||||
@@ -272,7 +272,7 @@ const parseSizeToBytes = (size: string): number => {
|
||||
const match = size.match(/^([\d.]+)\s*([KMGT]?B)$/i);
|
||||
if (!match) return 0;
|
||||
const value = Number.parseFloat(match[1] as string);
|
||||
const unit = match[2].toUpperCase();
|
||||
const unit = (match[2] as string).toUpperCase();
|
||||
const multipliers: Record<string, number> = {
|
||||
B: 1,
|
||||
KB: 1024,
|
||||
|
||||
Reference in New Issue
Block a user