xKanban بهعنوان یک Single-Page Application (SPA) تکفایلی طراحی شده است که تمامی لایههای نمایش، منطق و داده را در یک فایل HTML واحد encapsulate میکند. این تصمیم معماری، اگرچه در نگاه اول غیرمعمول به نظر میرسد، اما با توجه به اهداف محصول (آفلاین بودن، قابلیت حمل و عدم وابستگی) منطقیترین انتخاب ممکن بوده است.
الف) نمودار معماری لایهای
🎨 Presentation Layer
Toolbar UI
Board Renderer
Column Renderer
Card Renderer
Modal System
Filter Panel
Stats Bar
Theme Engine
▼ Event Binding & State Observation ▼
⚙️ Application Logic Layer
ProjectManager
BoardManager
ColumnManager
CardManager
TagManager
FilterEngine
WebhookService
ShortcutHandler
HistoryTracker
▼ Read / Write / Sync ▼
💾 Data & Persistence Layer
AppState (In-Memory)
LocalStorage Adapter
AutoSave Engine
JSON Serializer
Export/Import Service
Recovery Manager
ب) مدل دادهای (Data Schema)
ساختار دادهای پروژه از یک سلسلهمراتب چهارسطحی پیروی میکند:
Project
├── id: UUID
├── title: string
├── description: string
├── createdAt: ISO8601
├── webhook: { enabled, url }
├── globalTags: [Tag]
└── boards: [
Board
├── id, title, backgroundColor
└── columns: [
Column
├── id, title, order
└── cards: [
Card
├── id, title, description
├── dueDate, assignees, tags
├── dependencies, checklist
└── history: [HistoryEntry]
]
]
]
ج) ماژولهای اصلی و متدهای کلیدی
در ادامه، مهمترین ماژولهای سیستم به همراه متدهای کلیدی هر کدام تشریح شدهاند. برای حفظ خوانایی، بدنه متدها خلاصه شده و تنها امضای آنها نمایش داده شده است:
📁 ماژول ProjectManager
-
initProject()
مقداردهی اولیه پروژه
-
loadProject(data)
بارگذاری پروژه از فایل JSON
-
saveProject(filename)
ذخیره پروژه بهصورت فایل JSON
-
updateProjectSettings(title, desc, webhook)
بهروزرسانی تنظیمات پروژه
-
getProjectStats()
محاسبه آمار کلی پروژه
📊 ماژول BoardManager
-
createBoard(title, description, bgColor)
ایجاد برد جدید
-
editBoard(boardId, data)
ویرایش برد موجود
-
deleteBoard(boardId)
حذف برد با تأیید کاربر
-
switchBoard(boardId)
تغییر برد فعال
-
renderBoardList()
رندر لیست بردها در منو
📑 ماژول ColumnManager
-
addColumn(boardId, title, bgColor, textColor)
افزودن ستون جدید به برد
-
editColumn(columnId, data)
ویرایش ویژگیهای ستون
-
deleteColumn(columnId)
حذف ستون و کارتهای آن
-
reorderColumns(draggedId, targetId)
تغییر ترتیب ستونها با Drag & Drop
-
renderColumns(boardId)
رندر ستونهای برد فعال
📝 ماژول CardManager
-
createCard(columnId, cardData)
ایجاد کارت جدید در ستون
-
updateCard(cardId, updates)
بهروزرسانی اطلاعات کارت
-
deleteCard(cardId)
حذف کارت از ستون
-
moveCard(cardId, fromColumnId, toColumnId)
جابجایی کارت بین ستونها
-
addChecklistItem(cardId, text)
افزودن آیتم به چکلیست
-
toggleChecklistItem(cardId, itemId)
تغییر وضعیت آیتم چکلیست
-
addDependency(cardId, dependOnCardId)
ایجاد وابستگی بین کارتها
-
assignMember(cardId, memberName)
تخصیص مسئول به کارت
-
getCardDueStatus(card)
تعیین وضعیت سررسید کارت
-
openCardModal(cardId)
باز کردن پنجره ویرایش کارت
🏷️ ماژول TagManager
-
createTag(name, color)
ایجاد تگ عمومی جدید
-
deleteTag(tagId)
حذف تگ و حذف از کارتها
-
assignTagToCard(cardId, tagId)
تخصیص تگ به کارت
-
removeTagFromCard(cardId, tagId)
حذف تگ از کارت
-
renderTagManager()
رندر پنل مدیریت تگها
🔍 ماژول FilterEngine
-
applyFilters(criteria)
اعمال فیلترهای چندبعدی
-
filterByTags(selectedTags)
فیلتر بر اساس تگها
-
filterByAssignees(selectedAssignees)
فیلتر بر اساس مسئولین
-
filterByDueStatus(status)
فیلتر بر اساس وضعیت سررسید
-
searchCards(query)
جستجوی متنی در کارتها
-
clearAllFilters()
پاکسازی تمام فیلترها
📡 ماژول WebhookService
-
sendEvent(eventType, payload)
ارسال رویداد به URL پیکربندیشده
-
testWebhook(url)
تست اتصال Webhook
-
buildEventPayload(eventType, data)
ساخت ساختار JSON استاندارد رویداد
💾 ماژول PersistenceEngine
-
autoSave()
ذخیره خودکار در LocalStorage
-
loadAutoSave()
بارگذاری دادههای ذخیرهشده خودکار
-
scheduleAutoSave()
زمانبندی ذخیره با Debounce
-
exportToJSON()
خروجی فایل JSON
-
importFromJSON(file)
بارگذاری از فایل JSON
-
exportToMarkdown(boardId)
خروجی فرمت Markdown
-
exportToCSV(boardId)
خروجی فرمت CSV
-
checkRecovery()
بررسی وجود دادههای بازیابی
⌨️ ماژول ShortcutHandler
-
registerShortcuts()
ثبت تمام میانبرهای کیبورد
-
handleKeyDown(event)
پردازش رویدادهای کیبورد
-
navigateCards(direction)
پیمایش بین کارتها با Tab
-
moveCardWithKeyboard(direction)
جابجایی کارت با Alt+Arrow
د) الگوهای طراحی بهکاررفته
| الگو |
محل استفاده |
هدف |
| State-Driven Rendering |
کل رابط کاربری |
رندر UI بر اساس وضعیت مرکزی AppState |
| Observer / Pub-Sub |
ارتباط ماژولها |
اطلاعرسانی تغییرات وضعیت به ماژولهای وابسته |
| Debouncing |
AutoSave Engine |
جلوگیری از نوشتن مکرر در LocalStorage |
| Factory |
ایجاد موجودیتها |
تولید اشیاء Card، Column، Board با UUID |
| Command |
Undo/Redo |
ذخیره عملیات برای امکان بازگشت |
| Singleton |
AppState |
یک منبع واحد حقیقت برای کل برنامه |
ه) جریان داده (Data Flow)
🔄 چرخه حیات یک عملیات کاربر:
۱. User Action: کاربر یک کارت را از ستون «در حال انجام» به ستون «تکمیلشده» میکشد.
۲. Event Capture: رویداد Drag & Drop توسط ColumnManager دریافت میشود.
۳. State Update: متد moveCard() از CardManager فراخوانی شده و AppState بهروزرسانی میشود.
۴. History Log: متد HistoryTracker.log() جابجایی را با timestamp ثبت میکند.
۵. Re-Render: متد renderColumns() رابط کاربری را با وضعیت جدید بهروزرسانی میکند.
۶. AutoSave: متد scheduleAutoSave() با تأخیر ۱ ثانیه، وضعیت را در LocalStorage ذخیره میکند.
۷. Webhook: در صورت فعال بودن، متد sendEvent('card.moved', payload) رویداد را ارسال میکند.
۸. Stats Update: متد getProjectStats() آمار نوار وضعیت را بهروزرسانی میکند.