diff --git a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_ping-icons-enabled.tsx b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_ping-icons-enabled.tsx
new file mode 100644
index 000000000..1631189dc
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_ping-icons-enabled.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import { Button, Group, Stack, Switch } from "@mantine/core";
+
+import type { RouterOutputs } from "@homarr/api";
+import { clientApi } from "@homarr/api/client";
+import { revalidatePathActionAsync } from "@homarr/common/client";
+import { useZodForm } from "@homarr/form";
+import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
+import { useI18n } from "@homarr/translation/client";
+import type { z } from "@homarr/validation";
+import { validation } from "@homarr/validation";
+
+interface PingIconsEnabledProps {
+ user: RouterOutputs["user"]["getById"];
+}
+
+export const PingIconsEnabled = ({ user }: PingIconsEnabledProps) => {
+ const t = useI18n();
+ const { mutate, isPending } = clientApi.user.changePingIconsEnabled.useMutation({
+ async onSettled() {
+ await revalidatePathActionAsync(`/manage/users/${user.id}`);
+ },
+ onSuccess(_, variables) {
+ form.setInitialValues({
+ pingIconsEnabled: variables.pingIconsEnabled,
+ });
+ showSuccessNotification({
+ message: t("user.action.changePingIconsEnabled.notification.success.message"),
+ });
+ },
+ onError() {
+ showErrorNotification({
+ message: t("user.action.changePingIconsEnabled.notification.error.message"),
+ });
+ },
+ });
+ const form = useZodForm(validation.user.pingIconsEnabled, {
+ initialValues: {
+ pingIconsEnabled: user.pingIconsEnabled,
+ },
+ });
+
+ const handleSubmit = (values: FormType) => {
+ mutate({
+ id: user.id,
+ ...values,
+ });
+ };
+
+ return (
+
+ );
+};
+
+type FormType = z.infer;
diff --git a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx
index e29a140f3..fa26d7bd1 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx
@@ -14,6 +14,7 @@ import { canAccessUserEditPage } from "../access";
import { ChangeHomeBoardForm } from "./_components/_change-home-board";
import { DeleteUserButton } from "./_components/_delete-user-button";
import { FirstDayOfWeek } from "./_components/_first-day-of-week";
+import { PingIconsEnabled } from "./_components/_ping-icons-enabled";
import { UserProfileAvatarForm } from "./_components/_profile-avatar-form";
import { UserProfileForm } from "./_components/_profile-form";
@@ -99,6 +100,11 @@ export default async function EditUserPage({ params }: Props) {
+
+ {tGeneral("item.accessibility")}
+
+
+
{isCredentialsUser && (
{
const user = await db.select().from(schema.users).where(eq(schema.users.id, defaultOwnerId));
expect(user).toHaveLength(1);
- expect(user[0]).toStrictEqual({
+ expect(user[0]).containSubset({
id: defaultOwnerId,
name: "ABC",
email: "abc@gmail.com",
emailVerified,
- salt: null,
- password: null,
- image: null,
- homeBoardId: null,
- provider: "credentials",
- colorScheme: "auto",
- firstDayOfWeek: 1,
});
});
@@ -289,18 +282,11 @@ describe("editProfile shoud update user", () => {
const user = await db.select().from(schema.users).where(eq(schema.users.id, defaultOwnerId));
expect(user).toHaveLength(1);
- expect(user[0]).toStrictEqual({
+ expect(user[0]).containSubset({
id: defaultOwnerId,
name: "ABC",
email: "myNewEmail@gmail.com",
emailVerified: null,
- salt: null,
- password: null,
- image: null,
- homeBoardId: null,
- provider: "credentials",
- colorScheme: "auto",
- firstDayOfWeek: 1,
});
});
});
@@ -317,40 +303,14 @@ describe("delete should delete user", () => {
{
id: createId(),
name: "User 1",
- email: null,
- emailVerified: null,
- image: null,
- password: null,
- salt: null,
- homeBoardId: null,
- provider: "ldap" as const,
- colorScheme: "auto" as const,
- firstDayOfWeek: 1 as const,
},
{
id: defaultOwnerId,
name: "User 2",
- email: null,
- emailVerified: null,
- image: null,
- password: null,
- salt: null,
- homeBoardId: null,
- colorScheme: "auto" as const,
- firstDayOfWeek: 1 as const,
},
{
id: createId(),
name: "User 3",
- email: null,
- emailVerified: null,
- image: null,
- password: null,
- salt: null,
- homeBoardId: null,
- provider: "oidc" as const,
- colorScheme: "auto" as const,
- firstDayOfWeek: 1 as const,
},
];
@@ -359,6 +319,8 @@ describe("delete should delete user", () => {
await caller.delete(defaultOwnerId);
const usersInDb = await db.select().from(schema.users);
- expect(usersInDb).toStrictEqual([initialUsers[0], initialUsers[2]]);
+ expect(usersInDb).toHaveLength(2);
+ expect(usersInDb[0]).containSubset(initialUsers[0]);
+ expect(usersInDb[1]).containSubset(initialUsers[2]);
});
});
diff --git a/packages/api/src/router/user.ts b/packages/api/src/router/user.ts
index d1a9719f3..805140540 100644
--- a/packages/api/src/router/user.ts
+++ b/packages/api/src/router/user.ts
@@ -209,6 +209,7 @@ export const userRouter = createTRPCRouter({
provider: true,
homeBoardId: true,
firstDayOfWeek: true,
+ pingIconsEnabled: true,
},
where: eq(users.id, input.userId),
});
@@ -376,6 +377,39 @@ export const userRouter = createTRPCRouter({
})
.where(eq(users.id, ctx.session.user.id));
}),
+ getPingIconsEnabledOrDefault: publicProcedure.query(async ({ ctx }) => {
+ if (!ctx.session?.user) {
+ return false;
+ }
+
+ const user = await ctx.db.query.users.findFirst({
+ columns: {
+ id: true,
+ pingIconsEnabled: true,
+ },
+ where: eq(users.id, ctx.session.user.id),
+ });
+
+ return user?.pingIconsEnabled ?? false;
+ }),
+ changePingIconsEnabled: protectedProcedure
+ .input(validation.user.pingIconsEnabled.and(validation.common.byId))
+ .mutation(async ({ input, ctx }) => {
+ // Only admins can change other users ping icons enabled
+ if (!ctx.session.user.permissions.includes("admin") && ctx.session.user.id !== input.id) {
+ throw new TRPCError({
+ code: "NOT_FOUND",
+ message: "User not found",
+ });
+ }
+
+ await ctx.db
+ .update(users)
+ .set({
+ pingIconsEnabled: input.pingIconsEnabled,
+ })
+ .where(eq(users.id, ctx.session.user.id));
+ }),
getFirstDayOfWeekForUserOrDefault: publicProcedure.query(async ({ ctx }) => {
if (!ctx.session?.user) {
return 1 as const;
@@ -394,7 +428,7 @@ export const userRouter = createTRPCRouter({
changeFirstDayOfWeek: protectedProcedure
.input(validation.user.firstDayOfWeek.and(validation.common.byId))
.mutation(async ({ input, ctx }) => {
- // Only admins can change other users' passwords
+ // Only admins can change other users first day of week
if (!ctx.session.user.permissions.includes("admin") && ctx.session.user.id !== input.id) {
throw new TRPCError({
code: "NOT_FOUND",
diff --git a/packages/db/migrations/mysql/0011_freezing_banshee.sql b/packages/db/migrations/mysql/0011_freezing_banshee.sql
new file mode 100644
index 000000000..f088e6b9d
--- /dev/null
+++ b/packages/db/migrations/mysql/0011_freezing_banshee.sql
@@ -0,0 +1 @@
+ALTER TABLE `user` ADD `pingIconsEnabled` boolean DEFAULT false NOT NULL;
\ No newline at end of file
diff --git a/packages/db/migrations/mysql/meta/0011_snapshot.json b/packages/db/migrations/mysql/meta/0011_snapshot.json
new file mode 100644
index 000000000..afa00d67d
--- /dev/null
+++ b/packages/db/migrations/mysql/meta/0011_snapshot.json
@@ -0,0 +1,1497 @@
+{
+ "version": "5",
+ "dialect": "mysql",
+ "id": "c2595909-0d92-4b2f-b934-6792271f52c0",
+ "prevId": "ea24896b-e311-49b3-855b-e50b224e7719",
+ "tables": {
+ "account": {
+ "name": "account",
+ "columns": {
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "providerAccountId": {
+ "name": "providerAccountId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "token_type": {
+ "name": "token_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "session_state": {
+ "name": "session_state",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "userId_idx": {
+ "name": "userId_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "account_userId_user_id_fk": {
+ "name": "account_userId_user_id_fk",
+ "tableFrom": "account",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "account_provider_providerAccountId_pk": {
+ "name": "account_provider_providerAccountId_pk",
+ "columns": ["provider", "providerAccountId"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "apiKey_userId_user_id_fk": {
+ "name": "apiKey_userId_user_id_fk",
+ "tableFrom": "apiKey",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "apiKey_id": {
+ "name": "apiKey_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "app": {
+ "name": "app",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "href": {
+ "name": "href",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "app_id": {
+ "name": "app_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "boardGroupPermission": {
+ "name": "boardGroupPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardGroupPermission_board_id_board_id_fk": {
+ "name": "boardGroupPermission_board_id_board_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardGroupPermission_group_id_group_id_fk": {
+ "name": "boardGroupPermission_group_id_group_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardGroupPermission_board_id_group_id_permission_pk": {
+ "name": "boardGroupPermission_board_id_group_id_permission_pk",
+ "columns": ["board_id", "group_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "boardUserPermission": {
+ "name": "boardUserPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardUserPermission_board_id_board_id_fk": {
+ "name": "boardUserPermission_board_id_board_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardUserPermission_user_id_user_id_fk": {
+ "name": "boardUserPermission_user_id_user_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardUserPermission_board_id_user_id_permission_pk": {
+ "name": "boardUserPermission_board_id_user_id_permission_pk",
+ "columns": ["board_id", "user_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "board": {
+ "name": "board",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(256)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "page_title": {
+ "name": "page_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "meta_title": {
+ "name": "meta_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "logo_image_url": {
+ "name": "logo_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "favicon_image_url": {
+ "name": "favicon_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_url": {
+ "name": "background_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_attachment": {
+ "name": "background_image_attachment",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('fixed')"
+ },
+ "background_image_repeat": {
+ "name": "background_image_repeat",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('no-repeat')"
+ },
+ "background_image_size": {
+ "name": "background_image_size",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('cover')"
+ },
+ "primary_color": {
+ "name": "primary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('#fa5252')"
+ },
+ "secondary_color": {
+ "name": "secondary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('#fd7e14')"
+ },
+ "opacity": {
+ "name": "opacity",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 100
+ },
+ "custom_css": {
+ "name": "custom_css",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "column_count": {
+ "name": "column_count",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 10
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "board_creator_id_user_id_fk": {
+ "name": "board_creator_id_user_id_fk",
+ "tableFrom": "board",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "board_id": {
+ "name": "board_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {
+ "board_name_unique": {
+ "name": "board_name_unique",
+ "columns": ["name"]
+ }
+ }
+ },
+ "groupMember": {
+ "name": "groupMember",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupMember_groupId_group_id_fk": {
+ "name": "groupMember_groupId_group_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "groupMember_userId_user_id_fk": {
+ "name": "groupMember_userId_user_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "groupMember_groupId_userId_pk": {
+ "name": "groupMember_groupId_userId_pk",
+ "columns": ["groupId", "userId"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "groupPermission": {
+ "name": "groupPermission",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupPermission_groupId_group_id_fk": {
+ "name": "groupPermission_groupId_group_id_fk",
+ "tableFrom": "groupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "group": {
+ "name": "group",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "owner_id": {
+ "name": "owner_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "group_owner_id_user_id_fk": {
+ "name": "group_owner_id_user_id_fk",
+ "tableFrom": "group",
+ "tableTo": "user",
+ "columnsFrom": ["owner_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "group_id": {
+ "name": "group_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "iconRepository": {
+ "name": "iconRepository",
+ "columns": {
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_slug": {
+ "name": "iconRepository_slug",
+ "type": "varchar(150)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "iconRepository_iconRepository_id": {
+ "name": "iconRepository_iconRepository_id",
+ "columns": ["iconRepository_id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "icon": {
+ "name": "icon",
+ "columns": {
+ "icon_id": {
+ "name": "icon_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_name": {
+ "name": "icon_name",
+ "type": "varchar(250)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_checksum": {
+ "name": "icon_checksum",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "icon_iconRepository_id_iconRepository_iconRepository_id_fk": {
+ "name": "icon_iconRepository_id_iconRepository_iconRepository_id_fk",
+ "tableFrom": "icon",
+ "tableTo": "iconRepository",
+ "columnsFrom": ["iconRepository_id"],
+ "columnsTo": ["iconRepository_id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "icon_icon_id": {
+ "name": "icon_icon_id",
+ "columns": ["icon_id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integrationGroupPermissions": {
+ "name": "integrationGroupPermissions",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationGroupPermissions_integration_id_integration_id_fk": {
+ "name": "integrationGroupPermissions_integration_id_integration_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationGroupPermissions_group_id_group_id_fk": {
+ "name": "integrationGroupPermissions_group_id_group_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integration_group_permission__pk": {
+ "name": "integration_group_permission__pk",
+ "columns": ["integration_id", "group_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integration_item": {
+ "name": "integration_item",
+ "columns": {
+ "item_id": {
+ "name": "item_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integration_item_item_id_item_id_fk": {
+ "name": "integration_item_item_id_item_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "item",
+ "columnsFrom": ["item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integration_item_integration_id_integration_id_fk": {
+ "name": "integration_item_integration_id_integration_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integration_item_item_id_integration_id_pk": {
+ "name": "integration_item_item_id_integration_id_pk",
+ "columns": ["item_id", "integration_id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integrationSecret": {
+ "name": "integrationSecret",
+ "columns": {
+ "kind": {
+ "name": "kind",
+ "type": "varchar(16)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration_secret__kind_idx": {
+ "name": "integration_secret__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ },
+ "integration_secret__updated_at_idx": {
+ "name": "integration_secret__updated_at_idx",
+ "columns": ["updated_at"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "integrationSecret_integration_id_integration_id_fk": {
+ "name": "integrationSecret_integration_id_integration_id_fk",
+ "tableFrom": "integrationSecret",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationSecret_integration_id_kind_pk": {
+ "name": "integrationSecret_integration_id_kind_pk",
+ "columns": ["integration_id", "kind"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integrationUserPermission": {
+ "name": "integrationUserPermission",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationUserPermission_integration_id_integration_id_fk": {
+ "name": "integrationUserPermission_integration_id_integration_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationUserPermission_user_id_user_id_fk": {
+ "name": "integrationUserPermission_user_id_user_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationUserPermission_integration_id_user_id_permission_pk": {
+ "name": "integrationUserPermission_integration_id_user_id_permission_pk",
+ "columns": ["integration_id", "user_id", "permission"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integration": {
+ "name": "integration",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "varchar(128)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration__kind_idx": {
+ "name": "integration__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "integration_id": {
+ "name": "integration_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "invite": {
+ "name": "invite",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expiration_date": {
+ "name": "expiration_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "invite_creator_id_user_id_fk": {
+ "name": "invite_creator_id_user_id_fk",
+ "tableFrom": "invite",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "invite_id": {
+ "name": "invite_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {
+ "invite_token_unique": {
+ "name": "invite_token_unique",
+ "columns": ["token"]
+ }
+ }
+ },
+ "item": {
+ "name": "item",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "section_id": {
+ "name": "section_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "options": {
+ "name": "options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('{\"json\": {}}')"
+ },
+ "advanced_options": {
+ "name": "advanced_options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('{\"json\": {}}')"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "item_section_id_section_id_fk": {
+ "name": "item_section_id_section_id_fk",
+ "tableFrom": "item",
+ "tableTo": "section",
+ "columnsFrom": ["section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "item_id": {
+ "name": "item_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "search_engine": {
+ "name": "search_engine",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "short": {
+ "name": "short",
+ "type": "varchar(8)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "url_template": {
+ "name": "url_template",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "search_engine_id": {
+ "name": "search_engine_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "section": {
+ "name": "section",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "board_id": {
+ "name": "board_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "parent_section_id": {
+ "name": "parent_section_id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "section_board_id_board_id_fk": {
+ "name": "section_board_id_board_id_fk",
+ "tableFrom": "section",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "section_parent_section_id_section_id_fk": {
+ "name": "section_parent_section_id_section_id_fk",
+ "tableFrom": "section",
+ "tableTo": "section",
+ "columnsFrom": ["parent_section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "section_id": {
+ "name": "section_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "serverSetting": {
+ "name": "serverSetting",
+ "columns": {
+ "key": {
+ "name": "key",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "('{\"json\": {}}')"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "serverSetting_key": {
+ "name": "serverSetting_key",
+ "columns": ["key"]
+ }
+ },
+ "uniqueConstraints": {
+ "serverSetting_key_unique": {
+ "name": "serverSetting_key_unique",
+ "columns": ["key"]
+ }
+ }
+ },
+ "session": {
+ "name": "session",
+ "columns": {
+ "sessionToken": {
+ "name": "sessionToken",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "user_id_idx": {
+ "name": "user_id_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "session_userId_user_id_fk": {
+ "name": "session_userId_user_id_fk",
+ "tableFrom": "session",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "session_sessionToken": {
+ "name": "session_sessionToken",
+ "columns": ["sessionToken"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "user": {
+ "name": "user",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailVerified": {
+ "name": "emailVerified",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'credentials'"
+ },
+ "homeBoardId": {
+ "name": "homeBoardId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "colorScheme": {
+ "name": "colorScheme",
+ "type": "varchar(5)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'auto'"
+ },
+ "firstDayOfWeek": {
+ "name": "firstDayOfWeek",
+ "type": "tinyint",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "pingIconsEnabled": {
+ "name": "pingIconsEnabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "user_homeBoardId_board_id_fk": {
+ "name": "user_homeBoardId_board_id_fk",
+ "tableFrom": "user",
+ "tableTo": "board",
+ "columnsFrom": ["homeBoardId"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "user_id": {
+ "name": "user_id",
+ "columns": ["id"]
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "verificationToken": {
+ "name": "verificationToken",
+ "columns": {
+ "identifier": {
+ "name": "identifier",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "verificationToken_identifier_token_pk": {
+ "name": "verificationToken_identifier_token_pk",
+ "columns": ["identifier", "token"]
+ }
+ },
+ "uniqueConstraints": {}
+ }
+ },
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "tables": {},
+ "indexes": {}
+ }
+}
diff --git a/packages/db/migrations/mysql/meta/_journal.json b/packages/db/migrations/mysql/meta/_journal.json
index dacc6be5a..0c9a41d33 100644
--- a/packages/db/migrations/mysql/meta/_journal.json
+++ b/packages/db/migrations/mysql/meta/_journal.json
@@ -78,6 +78,13 @@
"when": 1728142597094,
"tag": "0010_melted_pestilence",
"breakpoints": true
+ },
+ {
+ "idx": 11,
+ "version": "5",
+ "when": 1728490046896,
+ "tag": "0011_freezing_banshee",
+ "breakpoints": true
}
]
}
diff --git a/packages/db/migrations/sqlite/0011_classy_angel.sql b/packages/db/migrations/sqlite/0011_classy_angel.sql
new file mode 100644
index 000000000..10f3d6bf5
--- /dev/null
+++ b/packages/db/migrations/sqlite/0011_classy_angel.sql
@@ -0,0 +1 @@
+ALTER TABLE `user` ADD `pingIconsEnabled` integer DEFAULT false NOT NULL;
\ No newline at end of file
diff --git a/packages/db/migrations/sqlite/meta/0011_snapshot.json b/packages/db/migrations/sqlite/meta/0011_snapshot.json
new file mode 100644
index 000000000..b3bf026e0
--- /dev/null
+++ b/packages/db/migrations/sqlite/meta/0011_snapshot.json
@@ -0,0 +1,1430 @@
+{
+ "version": "6",
+ "dialect": "sqlite",
+ "id": "7c2e4a9e-350a-4551-90d9-bdfa90db58ee",
+ "prevId": "52be1539-1b06-4581-8347-ce2102e782c7",
+ "tables": {
+ "account": {
+ "name": "account",
+ "columns": {
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "providerAccountId": {
+ "name": "providerAccountId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "token_type": {
+ "name": "token_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "session_state": {
+ "name": "session_state",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "userId_idx": {
+ "name": "userId_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "account_userId_user_id_fk": {
+ "name": "account_userId_user_id_fk",
+ "tableFrom": "account",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "account_provider_providerAccountId_pk": {
+ "columns": ["provider", "providerAccountId"],
+ "name": "account_provider_providerAccountId_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apiKey": {
+ "name": "apiKey",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "apiKey_userId_user_id_fk": {
+ "name": "apiKey_userId_user_id_fk",
+ "tableFrom": "apiKey",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "app": {
+ "name": "app",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "href": {
+ "name": "href",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "boardGroupPermission": {
+ "name": "boardGroupPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardGroupPermission_board_id_board_id_fk": {
+ "name": "boardGroupPermission_board_id_board_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardGroupPermission_group_id_group_id_fk": {
+ "name": "boardGroupPermission_group_id_group_id_fk",
+ "tableFrom": "boardGroupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardGroupPermission_board_id_group_id_permission_pk": {
+ "columns": ["board_id", "group_id", "permission"],
+ "name": "boardGroupPermission_board_id_group_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "boardUserPermission": {
+ "name": "boardUserPermission",
+ "columns": {
+ "board_id": {
+ "name": "board_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "boardUserPermission_board_id_board_id_fk": {
+ "name": "boardUserPermission_board_id_board_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "boardUserPermission_user_id_user_id_fk": {
+ "name": "boardUserPermission_user_id_user_id_fk",
+ "tableFrom": "boardUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "boardUserPermission_board_id_user_id_permission_pk": {
+ "columns": ["board_id", "user_id", "permission"],
+ "name": "boardUserPermission_board_id_user_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "board": {
+ "name": "board",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "page_title": {
+ "name": "page_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "meta_title": {
+ "name": "meta_title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "logo_image_url": {
+ "name": "logo_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "favicon_image_url": {
+ "name": "favicon_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_url": {
+ "name": "background_image_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "background_image_attachment": {
+ "name": "background_image_attachment",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'fixed'"
+ },
+ "background_image_repeat": {
+ "name": "background_image_repeat",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'no-repeat'"
+ },
+ "background_image_size": {
+ "name": "background_image_size",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'cover'"
+ },
+ "primary_color": {
+ "name": "primary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'#fa5252'"
+ },
+ "secondary_color": {
+ "name": "secondary_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'#fd7e14'"
+ },
+ "opacity": {
+ "name": "opacity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 100
+ },
+ "custom_css": {
+ "name": "custom_css",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "column_count": {
+ "name": "column_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 10
+ }
+ },
+ "indexes": {
+ "board_name_unique": {
+ "name": "board_name_unique",
+ "columns": ["name"],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {
+ "board_creator_id_user_id_fk": {
+ "name": "board_creator_id_user_id_fk",
+ "tableFrom": "board",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "groupMember": {
+ "name": "groupMember",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupMember_groupId_group_id_fk": {
+ "name": "groupMember_groupId_group_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "groupMember_userId_user_id_fk": {
+ "name": "groupMember_userId_user_id_fk",
+ "tableFrom": "groupMember",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "groupMember_groupId_userId_pk": {
+ "columns": ["groupId", "userId"],
+ "name": "groupMember_groupId_userId_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "groupPermission": {
+ "name": "groupPermission",
+ "columns": {
+ "groupId": {
+ "name": "groupId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "groupPermission_groupId_group_id_fk": {
+ "name": "groupPermission_groupId_group_id_fk",
+ "tableFrom": "groupPermission",
+ "tableTo": "group",
+ "columnsFrom": ["groupId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "group": {
+ "name": "group",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "owner_id": {
+ "name": "owner_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "group_owner_id_user_id_fk": {
+ "name": "group_owner_id_user_id_fk",
+ "tableFrom": "group",
+ "tableTo": "user",
+ "columnsFrom": ["owner_id"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "iconRepository": {
+ "name": "iconRepository",
+ "columns": {
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_slug": {
+ "name": "iconRepository_slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "icon": {
+ "name": "icon",
+ "columns": {
+ "icon_id": {
+ "name": "icon_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_name": {
+ "name": "icon_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_checksum": {
+ "name": "icon_checksum",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "iconRepository_id": {
+ "name": "iconRepository_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "icon_iconRepository_id_iconRepository_iconRepository_id_fk": {
+ "name": "icon_iconRepository_id_iconRepository_iconRepository_id_fk",
+ "tableFrom": "icon",
+ "tableTo": "iconRepository",
+ "columnsFrom": ["iconRepository_id"],
+ "columnsTo": ["iconRepository_id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "integrationGroupPermissions": {
+ "name": "integrationGroupPermissions",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "group_id": {
+ "name": "group_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationGroupPermissions_integration_id_integration_id_fk": {
+ "name": "integrationGroupPermissions_integration_id_integration_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationGroupPermissions_group_id_group_id_fk": {
+ "name": "integrationGroupPermissions_group_id_group_id_fk",
+ "tableFrom": "integrationGroupPermissions",
+ "tableTo": "group",
+ "columnsFrom": ["group_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationGroupPermissions_integration_id_group_id_permission_pk": {
+ "columns": ["integration_id", "group_id", "permission"],
+ "name": "integrationGroupPermissions_integration_id_group_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integration_item": {
+ "name": "integration_item",
+ "columns": {
+ "item_id": {
+ "name": "item_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integration_item_item_id_item_id_fk": {
+ "name": "integration_item_item_id_item_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "item",
+ "columnsFrom": ["item_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integration_item_integration_id_integration_id_fk": {
+ "name": "integration_item_integration_id_integration_id_fk",
+ "tableFrom": "integration_item",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integration_item_item_id_integration_id_pk": {
+ "columns": ["item_id", "integration_id"],
+ "name": "integration_item_item_id_integration_id_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integrationSecret": {
+ "name": "integrationSecret",
+ "columns": {
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration_secret__kind_idx": {
+ "name": "integration_secret__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ },
+ "integration_secret__updated_at_idx": {
+ "name": "integration_secret__updated_at_idx",
+ "columns": ["updated_at"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "integrationSecret_integration_id_integration_id_fk": {
+ "name": "integrationSecret_integration_id_integration_id_fk",
+ "tableFrom": "integrationSecret",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationSecret_integration_id_kind_pk": {
+ "columns": ["integration_id", "kind"],
+ "name": "integrationSecret_integration_id_kind_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integrationUserPermission": {
+ "name": "integrationUserPermission",
+ "columns": {
+ "integration_id": {
+ "name": "integration_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "permission": {
+ "name": "permission",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "integrationUserPermission_integration_id_integration_id_fk": {
+ "name": "integrationUserPermission_integration_id_integration_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "integration",
+ "columnsFrom": ["integration_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integrationUserPermission_user_id_user_id_fk": {
+ "name": "integrationUserPermission_user_id_user_id_fk",
+ "tableFrom": "integrationUserPermission",
+ "tableTo": "user",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "integrationUserPermission_integration_id_user_id_permission_pk": {
+ "columns": ["integration_id", "user_id", "permission"],
+ "name": "integrationUserPermission_integration_id_user_id_permission_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ },
+ "integration": {
+ "name": "integration",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "integration__kind_idx": {
+ "name": "integration__kind_idx",
+ "columns": ["kind"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "invite": {
+ "name": "invite",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expiration_date": {
+ "name": "expiration_date",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "invite_token_unique": {
+ "name": "invite_token_unique",
+ "columns": ["token"],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {
+ "invite_creator_id_user_id_fk": {
+ "name": "invite_creator_id_user_id_fk",
+ "tableFrom": "invite",
+ "tableTo": "user",
+ "columnsFrom": ["creator_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "item": {
+ "name": "item",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "section_id": {
+ "name": "section_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "options": {
+ "name": "options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'{\"json\": {}}'"
+ },
+ "advanced_options": {
+ "name": "advanced_options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'{\"json\": {}}'"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "item_section_id_section_id_fk": {
+ "name": "item_section_id_section_id_fk",
+ "tableFrom": "item",
+ "tableTo": "section",
+ "columnsFrom": ["section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "search_engine": {
+ "name": "search_engine",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "short": {
+ "name": "short",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "url_template": {
+ "name": "url_template",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "section": {
+ "name": "section",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "board_id": {
+ "name": "board_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "kind": {
+ "name": "kind",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "x_offset": {
+ "name": "x_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "y_offset": {
+ "name": "y_offset",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "width": {
+ "name": "width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "height": {
+ "name": "height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "parent_section_id": {
+ "name": "parent_section_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "section_board_id_board_id_fk": {
+ "name": "section_board_id_board_id_fk",
+ "tableFrom": "section",
+ "tableTo": "board",
+ "columnsFrom": ["board_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "section_parent_section_id_section_id_fk": {
+ "name": "section_parent_section_id_section_id_fk",
+ "tableFrom": "section",
+ "tableTo": "section",
+ "columnsFrom": ["parent_section_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "serverSetting": {
+ "name": "serverSetting",
+ "columns": {
+ "key": {
+ "name": "key",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'{\"json\": {}}'"
+ }
+ },
+ "indexes": {
+ "serverSetting_key_unique": {
+ "name": "serverSetting_key_unique",
+ "columns": ["key"],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "session": {
+ "name": "session",
+ "columns": {
+ "sessionToken": {
+ "name": "sessionToken",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userId": {
+ "name": "userId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {
+ "user_id_idx": {
+ "name": "user_id_idx",
+ "columns": ["userId"],
+ "isUnique": false
+ }
+ },
+ "foreignKeys": {
+ "session_userId_user_id_fk": {
+ "name": "session_userId_user_id_fk",
+ "tableFrom": "session",
+ "tableTo": "user",
+ "columnsFrom": ["userId"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "user": {
+ "name": "user",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailVerified": {
+ "name": "emailVerified",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "salt": {
+ "name": "salt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "provider": {
+ "name": "provider",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'credentials'"
+ },
+ "homeBoardId": {
+ "name": "homeBoardId",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "colorScheme": {
+ "name": "colorScheme",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'auto'"
+ },
+ "firstDayOfWeek": {
+ "name": "firstDayOfWeek",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "pingIconsEnabled": {
+ "name": "pingIconsEnabled",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "user_homeBoardId_board_id_fk": {
+ "name": "user_homeBoardId_board_id_fk",
+ "tableFrom": "user",
+ "tableTo": "board",
+ "columnsFrom": ["homeBoardId"],
+ "columnsTo": ["id"],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "verificationToken": {
+ "name": "verificationToken",
+ "columns": {
+ "identifier": {
+ "name": "identifier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires": {
+ "name": "expires",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "verificationToken_identifier_token_pk": {
+ "columns": ["identifier", "token"],
+ "name": "verificationToken_identifier_token_pk"
+ }
+ },
+ "uniqueConstraints": {}
+ }
+ },
+ "enums": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "indexes": {}
+ }
+}
diff --git a/packages/db/migrations/sqlite/meta/_journal.json b/packages/db/migrations/sqlite/meta/_journal.json
index 40d9bf4d0..99b2038fe 100644
--- a/packages/db/migrations/sqlite/meta/_journal.json
+++ b/packages/db/migrations/sqlite/meta/_journal.json
@@ -78,6 +78,13 @@
"when": 1728142590232,
"tag": "0010_gorgeous_stingray",
"breakpoints": true
+ },
+ {
+ "idx": 11,
+ "version": "6",
+ "when": 1728490026154,
+ "tag": "0011_classy_angel",
+ "breakpoints": true
}
]
}
diff --git a/packages/db/package.json b/packages/db/package.json
index 67ffa31ba..f5e38ba7b 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -22,8 +22,10 @@
"lint": "eslint",
"migration:mysql:generate": "drizzle-kit generate --config ./configs/mysql.config.ts",
"migration:mysql:run": "drizzle-kit migrate --config ./configs/mysql.config.ts",
+ "migration:mysql:drop": "drizzle-kit drop --config ./configs/mysql.config.ts",
"migration:sqlite:generate": "drizzle-kit generate --config ./configs/sqlite.config.ts",
"migration:sqlite:run": "drizzle-kit migrate --config ./configs/sqlite.config.ts",
+ "migration:sqlite:drop": "drizzle-kit drop --config ./configs/sqlite.config.ts",
"push:mysql": "drizzle-kit push --config ./configs/mysql.config.ts",
"push:sqlite": "drizzle-kit push --config ./configs/sqlite.config.ts",
"studio": "drizzle-kit studio --config ./configs/sqlite.config.ts",
diff --git a/packages/db/schema/mysql.ts b/packages/db/schema/mysql.ts
index 383ac2e5a..ec92ee53b 100644
--- a/packages/db/schema/mysql.ts
+++ b/packages/db/schema/mysql.ts
@@ -45,6 +45,7 @@ export const users = mysqlTable("user", {
}),
colorScheme: varchar("colorScheme", { length: 5 }).$type().default("auto").notNull(),
firstDayOfWeek: tinyint("firstDayOfWeek").$type().default(1).notNull(), // Defaults to Monday
+ pingIconsEnabled: boolean("pingIconsEnabled").default(false).notNull(),
});
export const accounts = mysqlTable(
diff --git a/packages/db/schema/sqlite.ts b/packages/db/schema/sqlite.ts
index cec5844c1..2b593b9d5 100644
--- a/packages/db/schema/sqlite.ts
+++ b/packages/db/schema/sqlite.ts
@@ -46,6 +46,7 @@ export const users = sqliteTable("user", {
}),
colorScheme: text("colorScheme").$type().default("auto").notNull(),
firstDayOfWeek: int("firstDayOfWeek").$type().default(1).notNull(), // Defaults to Monday
+ pingIconsEnabled: int("pingIconsEnabled", { mode: "boolean" }).default(false).notNull(),
});
export const accounts = sqliteTable(
diff --git a/packages/translation/src/lang/en.ts b/packages/translation/src/lang/en.ts
index f61c5da64..e5e8a64ca 100644
--- a/packages/translation/src/lang/en.ts
+++ b/packages/translation/src/lang/en.ts
@@ -48,6 +48,9 @@ export default {
homeBoard: {
label: "Home board",
},
+ pingIconsEnabled: {
+ label: "Use icons for pings",
+ },
},
error: {
usernameTaken: "Username already taken",
@@ -116,6 +119,16 @@ export default {
},
},
},
+ changePingIconsEnabled: {
+ notification: {
+ success: {
+ message: "Ping icons toggled successfully",
+ },
+ error: {
+ message: "Unable to toggle ping icons",
+ },
+ },
+ },
manageAvatar: {
changeImage: {
label: "Change image",
@@ -1703,6 +1716,7 @@ export default {
language: "Language & Region",
board: "Home board",
firstDayOfWeek: "First day of the week",
+ accessibility: "Accessibility",
},
},
security: {
diff --git a/packages/validation/src/user.ts b/packages/validation/src/user.ts
index e44395e67..566e43363 100644
--- a/packages/validation/src/user.ts
+++ b/packages/validation/src/user.ts
@@ -108,6 +108,10 @@ const firstDayOfWeekSchema = z.object({
firstDayOfWeek: z.custom((value) => z.number().min(0).max(6).safeParse(value).success),
});
+const pingIconsEnabledSchema = z.object({
+ pingIconsEnabled: z.boolean(),
+});
+
export const userSchemas = {
signIn: signInSchema,
registration: registrationSchema,
@@ -121,4 +125,5 @@ export const userSchemas = {
changePasswordApi: changePasswordApiSchema,
changeColorScheme: changeColorSchemeSchema,
firstDayOfWeek: firstDayOfWeekSchema,
+ pingIconsEnabled: pingIconsEnabledSchema,
};
diff --git a/packages/widgets/src/app/component.tsx b/packages/widgets/src/app/component.tsx
index eec922902..4b4cbe309 100644
--- a/packages/widgets/src/app/component.tsx
+++ b/packages/widgets/src/app/component.tsx
@@ -3,6 +3,7 @@
import type { PropsWithChildren } from "react";
import { Suspense } from "react";
import { Flex, Text, Tooltip, UnstyledButton } from "@mantine/core";
+import { IconLoader } from "@tabler/icons-react";
import combineClasses from "clsx";
import { clientApi } from "@homarr/api/client";
@@ -59,7 +60,7 @@ export default function AppWidget({ options, isEditMode }: WidgetComponentProps<
{options.pingEnabled && app.href ? (
- }>
+ }>
) : null}
diff --git a/packages/widgets/src/app/ping/ping-dot.tsx b/packages/widgets/src/app/ping/ping-dot.tsx
index b54262f28..fca47c09b 100644
--- a/packages/widgets/src/app/ping/ping-dot.tsx
+++ b/packages/widgets/src/app/ping/ping-dot.tsx
@@ -1,23 +1,33 @@
import type { MantineColor } from "@mantine/core";
import { Box, Tooltip } from "@mantine/core";
+import { clientApi } from "@homarr/api/client";
+import type { TablerIcon } from "@homarr/ui";
+
interface PingDotProps {
+ icon: TablerIcon;
color: MantineColor;
tooltip: string;
}
-export const PingDot = ({ color, tooltip }: PingDotProps) => {
+export const PingDot = ({ color, tooltip, ...props }: PingDotProps) => {
+ const [pingIconsEnabled] = clientApi.user.getPingIconsEnabledOrDefault.useSuspenseQuery();
+
return (
-
+ {pingIconsEnabled ? (
+
+ ) : (
+
+ )}
);
diff --git a/packages/widgets/src/app/ping/ping-indicator.tsx b/packages/widgets/src/app/ping/ping-indicator.tsx
index 058600257..1bf781427 100644
--- a/packages/widgets/src/app/ping/ping-indicator.tsx
+++ b/packages/widgets/src/app/ping/ping-indicator.tsx
@@ -1,4 +1,5 @@
import { useState } from "react";
+import { IconCheck, IconX } from "@tabler/icons-react";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
@@ -32,9 +33,12 @@ export const PingIndicator = ({ href }: PingIndicatorProps) => {
},
);
+ const isError = "error" in pingResult || pingResult.statusCode >= 500;
+
return (
= 500 ? "red" : "green"}
+ icon={isError ? IconX : IconCheck}
+ color={isError ? "red" : "green"}
tooltip={"statusCode" in pingResult ? pingResult.statusCode.toString() : pingResult.error}
/>
);