mirror of
https://github.com/d0zingcat/alert-message-center.git
synced 2026-05-13 15:09:19 +00:00
feat: add icon and meta
Signed-off-by: d0zingcat <iamtangli42@gmail.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -34,7 +34,6 @@ pnpm-debug.log*
|
|||||||
# Database
|
# Database
|
||||||
*.sqlite
|
*.sqlite
|
||||||
*.db
|
*.db
|
||||||
apps/server/drizzle/meta
|
|
||||||
|
|
||||||
# Bun
|
# Bun
|
||||||
.bun/
|
.bun/
|
||||||
|
|||||||
11
CHANGELOG.md
11
CHANGELOG.md
@@ -4,6 +4,17 @@
|
|||||||
|
|
||||||
本文件的格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
本文件的格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||||
并且本项目遵循 [语义化版本 (Semantic Versioning)](https://semver.org/lang/zh-CN/spec/v2.0.0.html)。
|
并且本项目遵循 [语义化版本 (Semantic Versioning)](https://semver.org/lang/zh-CN/spec/v2.0.0.html)。
|
||||||
|
|
||||||
|
## [1.3.0] - 2026-01-15
|
||||||
|
|
||||||
|
### 新增
|
||||||
|
- **视觉品牌**: 引入了自定义图标和 Favicon。
|
||||||
|
- 为 "Alert Message Center" 专门设计的现代 Indigo 主题 Logo。
|
||||||
|
- 将 Logo 集成到登录界面和顶部导航栏,替换了通用的 Activity 图标。
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- **部署可靠性**: 修复了 Docker 环境下数据库迁移失败的问题。
|
||||||
|
- 在 `.gitignore` 中移除了对 `apps/server/drizzle/meta` 的忽略,确保 Drizzle 迁移日志 (`_journal.json`) 能正确打包进 Docker 镜像。
|
||||||
|
|
||||||
## [1.2.7] - 2026-01-15
|
## [1.2.7] - 2026-01-15
|
||||||
|
|
||||||
|
|||||||
514
apps/server/drizzle/meta/0000_snapshot.json
Normal file
514
apps/server/drizzle/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
{
|
||||||
|
"id": "bc7589bc-5cb6-40c9-ab16-2076a0a2133f",
|
||||||
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "postgresql",
|
||||||
|
"tables": {
|
||||||
|
"public.alert_logs": {
|
||||||
|
"name": "alert_logs",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"task_id": {
|
||||||
|
"name": "task_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"name": "error",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"alert_logs_task_id_alert_tasks_id_fk": {
|
||||||
|
"name": "alert_logs_task_id_alert_tasks_id_fk",
|
||||||
|
"tableFrom": "alert_logs",
|
||||||
|
"tableTo": "alert_tasks",
|
||||||
|
"columnsFrom": [
|
||||||
|
"task_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.alert_tasks": {
|
||||||
|
"name": "alert_tasks",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"topic_slug": {
|
||||||
|
"name": "topic_slug",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"sender_id": {
|
||||||
|
"name": "sender_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "'pending'"
|
||||||
|
},
|
||||||
|
"recipient_count": {
|
||||||
|
"name": "recipient_count",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"success_count": {
|
||||||
|
"name": "success_count",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"payload": {
|
||||||
|
"name": "payload",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"name": "error",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"alert_tasks_sender_id_users_id_fk": {
|
||||||
|
"name": "alert_tasks_sender_id_users_id_fk",
|
||||||
|
"tableFrom": "alert_tasks",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"sender_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.known_group_chats": {
|
||||||
|
"name": "known_group_chats",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"chat_id": {
|
||||||
|
"name": "chat_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"last_active_at": {
|
||||||
|
"name": "last_active_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.subscriptions": {
|
||||||
|
"name": "subscriptions",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"topic_id": {
|
||||||
|
"name": "topic_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"subscriptions_user_id_users_id_fk": {
|
||||||
|
"name": "subscriptions_user_id_users_id_fk",
|
||||||
|
"tableFrom": "subscriptions",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"subscriptions_topic_id_topics_id_fk": {
|
||||||
|
"name": "subscriptions_topic_id_topics_id_fk",
|
||||||
|
"tableFrom": "subscriptions",
|
||||||
|
"tableTo": "topics",
|
||||||
|
"columnsFrom": [
|
||||||
|
"topic_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"subscriptions_user_id_topic_id_pk": {
|
||||||
|
"name": "subscriptions_user_id_topic_id_pk",
|
||||||
|
"columns": [
|
||||||
|
"user_id",
|
||||||
|
"topic_id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.topic_group_chats": {
|
||||||
|
"name": "topic_group_chats",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"topic_id": {
|
||||||
|
"name": "topic_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"chat_id": {
|
||||||
|
"name": "chat_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"created_by": {
|
||||||
|
"name": "created_by",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"topic_group_chats_topic_id_topics_id_fk": {
|
||||||
|
"name": "topic_group_chats_topic_id_topics_id_fk",
|
||||||
|
"tableFrom": "topic_group_chats",
|
||||||
|
"tableTo": "topics",
|
||||||
|
"columnsFrom": [
|
||||||
|
"topic_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"topic_group_chats_created_by_users_id_fk": {
|
||||||
|
"name": "topic_group_chats_created_by_users_id_fk",
|
||||||
|
"tableFrom": "topic_group_chats",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"created_by"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.topics": {
|
||||||
|
"name": "topics",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"slug": {
|
||||||
|
"name": "slug",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"name": "description",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "'approved'"
|
||||||
|
},
|
||||||
|
"created_by": {
|
||||||
|
"name": "created_by",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"approved_by": {
|
||||||
|
"name": "approved_by",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"topics_created_by_users_id_fk": {
|
||||||
|
"name": "topics_created_by_users_id_fk",
|
||||||
|
"tableFrom": "topics",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"created_by"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"topics_approved_by_users_id_fk": {
|
||||||
|
"name": "topics_approved_by_users_id_fk",
|
||||||
|
"tableFrom": "topics",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"approved_by"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"topics_slug_unique": {
|
||||||
|
"name": "topics_slug_unique",
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"columns": [
|
||||||
|
"slug"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.users": {
|
||||||
|
"name": "users",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"feishu_user_id": {
|
||||||
|
"name": "feishu_user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"is_admin": {
|
||||||
|
"name": "is_admin",
|
||||||
|
"type": "boolean",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"personal_token": {
|
||||||
|
"name": "personal_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"users_email_unique": {
|
||||||
|
"name": "users_email_unique",
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"users_personal_token_unique": {
|
||||||
|
"name": "users_personal_token_unique",
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"columns": [
|
||||||
|
"personal_token"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enums": {},
|
||||||
|
"schemas": {},
|
||||||
|
"sequences": {},
|
||||||
|
"roles": {},
|
||||||
|
"policies": {},
|
||||||
|
"views": {},
|
||||||
|
"_meta": {
|
||||||
|
"columns": {},
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
apps/server/drizzle/meta/_journal.json
Normal file
13
apps/server/drizzle/meta/_journal.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "postgresql",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"idx": 0,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1768448660268,
|
||||||
|
"tag": "0000_stiff_electro",
|
||||||
|
"breakpoints": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||||
|
<link rel="apple-touch-icon" href="/icon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Alert Message Center</title>
|
<title>Alert Message Center</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
BIN
apps/web/public/favicon.png
Normal file
BIN
apps/web/public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 484 KiB |
BIN
apps/web/public/icon.png
Normal file
BIN
apps/web/public/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 484 KiB |
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
Activity,
|
|
||||||
Hash,
|
Hash,
|
||||||
LogIn,
|
LogIn,
|
||||||
LogOut,
|
LogOut,
|
||||||
@@ -38,7 +37,7 @@ function App() {
|
|||||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
||||||
<div className="max-w-md w-full bg-white shadow-lg rounded-lg p-8">
|
<div className="max-w-md w-full bg-white shadow-lg rounded-lg p-8">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<Activity className="h-16 w-16 text-indigo-600 mx-auto mb-4" />
|
<img src="/icon.png" alt="Logo" className="h-16 w-16 mx-auto mb-4" />
|
||||||
<h1 className="text-3xl font-bold text-gray-900 mb-2">
|
<h1 className="text-3xl font-bold text-gray-900 mb-2">
|
||||||
Alert Message Center
|
Alert Message Center
|
||||||
</h1>
|
</h1>
|
||||||
@@ -66,7 +65,7 @@ function App() {
|
|||||||
<div className="flex justify-between h-16">
|
<div className="flex justify-between h-16">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="flex-shrink-0 flex items-center">
|
<div className="flex-shrink-0 flex items-center">
|
||||||
<Activity className="h-8 w-8 text-indigo-600" />
|
<img src="/icon.png" alt="Logo" className="h-8 w-8" />
|
||||||
<span className="ml-2 text-xl font-bold text-gray-900">
|
<span className="ml-2 text-xl font-bold text-gray-900">
|
||||||
Alert Message Center
|
Alert Message Center
|
||||||
</span>
|
</span>
|
||||||
@@ -76,11 +75,10 @@ function App() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setActiveTab("admin")}
|
onClick={() => setActiveTab("admin")}
|
||||||
className={`${
|
className={`${activeTab === "admin"
|
||||||
activeTab === "admin"
|
? "border-indigo-500 text-gray-900"
|
||||||
? "border-indigo-500 text-gray-900"
|
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
||||||
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium`}
|
||||||
} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium`}
|
|
||||||
>
|
>
|
||||||
<Settings className="mr-2 h-4 w-4" />
|
<Settings className="mr-2 h-4 w-4" />
|
||||||
Admin
|
Admin
|
||||||
@@ -89,11 +87,10 @@ function App() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setActiveTab("topics")}
|
onClick={() => setActiveTab("topics")}
|
||||||
className={`${
|
className={`${activeTab === "topics"
|
||||||
activeTab === "topics"
|
? "border-indigo-500 text-gray-900"
|
||||||
? "border-indigo-500 text-gray-900"
|
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
||||||
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium`}
|
||||||
} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium`}
|
|
||||||
>
|
>
|
||||||
<Hash className="mr-2 h-4 w-4" />
|
<Hash className="mr-2 h-4 w-4" />
|
||||||
Topics
|
Topics
|
||||||
@@ -102,11 +99,10 @@ function App() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setActiveTab("users")}
|
onClick={() => setActiveTab("users")}
|
||||||
className={`${
|
className={`${activeTab === "users"
|
||||||
activeTab === "users"
|
? "border-indigo-500 text-gray-900"
|
||||||
? "border-indigo-500 text-gray-900"
|
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
||||||
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium`}
|
||||||
} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium`}
|
|
||||||
>
|
>
|
||||||
<Users className="mr-2 h-4 w-4" />
|
<Users className="mr-2 h-4 w-4" />
|
||||||
Users
|
Users
|
||||||
|
|||||||
@@ -223,11 +223,10 @@ The database schema is defined in `apps/server/src/db/schema.ts`.
|
|||||||
- Deployment Architecture: A single container runs the Bun server, which serves API requests and static frontend assets (via `hono/bun`'s `serveStatic`).
|
- Deployment Architecture: A single container runs the Bun server, which serves API requests and static frontend assets (via `hono/bun`'s `serveStatic`).
|
||||||
- **Database Initialization**: The Docker entrypoint automatically runs `bun run db:migrate:deploy` before starting the server to ensure the schema is up-to-date in new environments.
|
- **Database Initialization**: The Docker entrypoint automatically runs `bun run db:migrate:deploy` before starting the server to ensure the schema is up-to-date in new environments.
|
||||||
- **Token Migration**: The `db:migrate:deploy` script (defined in `src/db/migrate.ts`) also handles legacy user token shortening to maintain consistency with the 8-character token logic introduced in v1.2.6.
|
- **Token Migration**: The `db:migrate:deploy` script (defined in `src/db/migrate.ts`) also handles legacy user token shortening to maintain consistency with the 8-character token logic introduced in v1.2.6.
|
||||||
|
- **Drizzle Meta**: The `apps/server/drizzle/meta` directory MUST NOT be ignored by git (it was previously explicitly excluded in `.gitignore` but has been restored). This directory contains `_journal.json`, which is essential for `drizzle-kit` and the runtime migrator to verify migration integrity. Without it, migrations will fail in clean environments like Docker containers.
|
||||||
|
|
||||||
## 8. Core Documents
|
## 8. Core Documents
|
||||||
|
|
||||||
- **[README.md](file:///Users/lilithgames/Workspace/dap/alert-message-center/README.md)**: Main project documentation, including quick start, tech stack overview, and Webhook usage guide.
|
- **[README.md](file:///Users/lilithgames/Workspace/play/alert-message-center/README.md)**: Main project documentation, including quick start, tech stack overview, and Webhook usage guide.
|
||||||
- **[CHANGELOG.md](file:///Users/lilithgames/Workspace/dap/alert-message-center/CHANGELOG.md)**: Record of version changes, following the Keep a Changelog specification.
|
- **[CHANGELOG.md](file:///Users/lilithgames/Workspace/play/alert-message-center/CHANGELOG.md)**: Record of version changes, following the Keep a Changelog specification.
|
||||||
- **[todo.md](file:///Users/lilithgames/Workspace/dap/alert-message-center/todo.md)**: Task tracking and upcoming features.
|
- **[todo.md](file:///Users/lilithgames/Workspace/play/alert-message-center/todo.md)**: Task tracking and upcoming features.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
3
todo.md
3
todo.md
@@ -31,3 +31,6 @@
|
|||||||
- [x] **Frontend Resilience**: Hardened API calls to prevent crashes on empty data or env access errors.
|
- [x] **Frontend Resilience**: Hardened API calls to prevent crashes on empty data or env access errors.
|
||||||
- [x] **CI & Type Safety**: Resolved all TypeScript errors and Biome formatting issues to ensure a healthy CI pipeline.
|
- [x] **CI & Type Safety**: Resolved all TypeScript errors and Biome formatting issues to ensure a healthy CI pipeline.
|
||||||
- [x] **User Token Shortening**: Shortened `personalToken` to 8 characters and integrated automated migration into the deployment script.
|
- [x] **User Token Shortening**: Shortened `personalToken` to 8 characters and integrated automated migration into the deployment script.
|
||||||
|
- [x] **Visual Identity**: Added custom logo, favicon and integrated them into the UI (login/navbar).
|
||||||
|
- [x] **Migration Robustness**: Fixed migration failures in Docker by un-ignoring the drizzle meta directory.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user