На основе анализа ведущих PM систем (Jira, Linear, Notion, Asana, Monday, ClickUp, Basecamp).
Workspace (контейнер для организации)
├── Space (группировка работы: отдел, проект, инициатива)
│ ├── Project (место для работы)
│ │ ├── Task (основная единица)
│ │ │ ├── Subtask (вложенная задача)
│ │ │ ├── Comment (обсуждение)
│ │ │ ├── Attachment (файлы)
│ │ │ └── Activity Log (история)
│ │ │
│ │ ├── View (List, Board, Gantt, Calendar, Timeline)
│ │ ├── Status/Workflow (настройки статусов)
│ │ ├── Custom Fields (настройки полей)
│ │ └── Settings (permissions, archive, etc.)
│ │
│ └── Document (опционально: встроенные docs)
│
├── Team (группировка людей)
│ ├── Members
│ └── Permissions
│
└── Integration Settings (external services)
interface Task {
// Идентификаторы
id: string; // UUID или TASK-123
projectId: string;
spaceId: string;
// Основной контент
title: string; // обязательное
description: string; // опциональное, может быть rich text
// Статус и рабочий поток
status: TaskStatus; // Todo, In Progress, Done, etc.
priority: Priority; // Low, Medium, High, Urgent
// Люди
assignees: User[]; // может быть несколько
creator: User;
watchers: User[];
// Даты
createdAt: DateTime;
updatedAt: DateTime;
dueDate?: DateTime;
startDate?: DateTime;
completedAt?: DateTime;
// Категоризация
labels: Label[]; // M:M тэги
customFields: CustomField[]; // пользовательские поля
// Иерархия
parentTaskId?: string; // для подзадач
subtasks?: Task[];
// Связи
dependencies: Dependency[]; // FS, SS, FF, SF типы
relatedTasks: Task[]; // M:M связи (duplicate, blocks, etc.)
// Содержимое
comments: Comment[];
attachments: Attachment[];
activityLog: Activity[];
// Оценки (опционально)
estimatedPoints?: number;
actualTime?: number;
// Архив
archivedAt?: DateTime;
}
type TaskStatus = 'backlog' | 'todo' | 'in_progress' | 'in_review' | 'done' | 'archived';
type Priority = 'low' | 'medium' | 'high' | 'urgent';
interface Dependency {
sourceTaskId: string;
targetTaskId: string;
type: 'finish-to-start' | 'start-to-start' | 'finish-to-finish' | 'start-to-finish';
}
interface Project {
id: string;
spaceId: string;
// Основное
name: string;
description: string;
icon?: string;
color?: string;
// Структура
status: 'active' | 'paused' | 'archived';
// Конфигурация
defaultView: ViewType; // List, Board, Gantt, Calendar, Timeline
customFields: CustomFieldDefinition[];
workflows: WorkflowDefinition[];
// Люди
owner: User;
members: User[];
// Важные даты
startDate?: DateTime;
dueDate?: DateTime;
completedAt?: DateTime;
createdAt: DateTime;
updatedAt: DateTime;
// Статистика
taskCount: number;
completedTaskCount: number;
// Архив
archivedAt?: DateTime;
}
interface WorkflowDefinition {
id: string;
name: string;
statuses: WorkflowStatus[]; // какие статусы доступны
transitions: Transition[]; // какие переходы разрешены
}
interface Transition {
fromStatus: string;
toStatus: string;
allowedRoles?: string[]; // кто может делать этот переход
}
interface Comment {
id: string;
taskId: string;
content: string; // может быть rich text
mentions: User[]; // @mentions
creator: User;
createdAt: DateTime;
updatedAt: DateTime;
attachments: Attachment[];
reactions: Reaction[]; // emoji reactions
// Нить для ответов
parentCommentId?: string;
replies?: Comment[];
archivedAt?: DateTime;
}
interface Activity {
id: string;
taskId: string;
actor: User; // кто сделал изменение
action: ActivityType;
oldValue?: any;
newValue?: any;
createdAt: DateTime;
// Можно группировать (например, 5 статус changes в один hour)
}
type ActivityType =
| 'task_created'
| 'task_updated'
| 'status_changed'
| 'assignee_changed'
| 'comment_added'
| 'attachment_added'
| 'field_changed';
interface Attachment {
id: string;
taskId: string;
fileName: string;
fileSize: number;
mimeType: string;
url: string; // где хранится (S3, etc.)
previewUrl?: string; // для изображений
uploadedBy: User;
uploadedAt: DateTime;
version: number; // для версионирования
}
Project (1) ──────────→ (M) Task
Task (1) ──────────→ (M) Comment
Task (1) ──────────→ (M) Attachment
Task (1) ──────────→ (M) Activity
Task (0,1) ──────────→ (M) Task [parent-child hierarchy]
Task (M) ──────────↔ (M) Task [dependencies]
Task (M) ──────────↔ (M) User [assignees]
Task (M) ──────────↔ (M) Label [tags]
Project (1) ──────────→ (M) CustomField [values per task]
Project (1) ──────────→ (M) WorkflowDefinition
Каждый проект должен поддерживать несколько представлений одних и тех же данных:
┌─ Project: "Website Redesign" ─────────────────────────────────┐
│ [List] [Board] [Gantt] [Calendar] [Timeline] │
├─────────────────────────────────────────────────────────────────┤
│ Filter: [Status ▼] [Assignee ▼] [Label ▼] [Search...] │
│ Sort: [Priority ▼] [Due Date ▼] │
├─────────────────────────────────────────────────────────────────┤
│ # │ Title │ Status │ Assignee │ Due Date │
├───┼──────────────────────┼─────────────┼─────────────┼────────────┤
│ 1 │ Design header │ In Progress │ Alice ● │ Jan 15 │
│ 2 │ Create CSS reset │ Done │ Bob ● │ Jan 10 │
│ 3 │ Setup build tools │ Todo │ Unassigned │ Jan 20 │
└─────────────────────────────────────────────────────────────────┘
→ Click row = Task detail modal/page
Компоненты:
- Filterable & Sortable table
- Inline editing (title, status, etc.)
- Batch operations (multi-select)
- Export to CSV
┌─ Project: "Website Redesign" ─────────────────────────────────┐
│ [List] [Board] [Gantt] [Calendar] [Timeline] │
├─────────────────────────────────────────────────────────────────┤
│ Filter: [Assignee ▼] [Label ▼] [Search...] │
│
│ ┌─ Backlog ──┐ ┌─ Todo ────┐ ┌─ In Progress ┐ ┌─ Done ──┐
│ │ │ │ │ │ │ │ │
│ │ ┌─────────┐ │ │ ┌────────┐ │ │ ┌──────────┐ │ │ ┌─────┐ │
│ │ │Design │ │ │ │Setup │ │ │ │Create │ │ │ │CSS │ │
│ │ │header │ │ │ │build │ │ │ │database │ │ │ │reset│ │
│ │ │@Alice │ │ │ │tools │ │ │ │@Bob │ │ │ │@Bob │ │
│ │ └─────────┘ │ │ └────────┘ │ │ └──────────┘ │ │ └─────┘ │
│ │ │ │ │ │ │ │ │
│ └─────────────┘ └────────────┘ └──────────────┘ └─────────┘
│ Drag & drop for status change
└─────────────────────────────────────────────────────────────────┘
Компоненты:
- Drag & drop between columns
- Quick-add for new tasks in column
- Bulk actions (move all, etc.)
- Swimlanes (группировка по assignee/label)
┌─ Project: "Website Redesign" ─────────────────────────────────┐
│ [List] [Board] [Gantt] [Calendar] [Timeline] │
├─────────────────────────────────────────────────────────────────┤
│ ┌─ Design header ──────────● Jan 15 [Alice] │
│ ├─ Create CSS reset ──────● Jan 10 [Bob] │
│ ├─ Setup build tools ────────────●────────● Jan 20 [Unassigned] │
│ │ ╭─────────────┬─────┐ │
│ │ Jan 1 Jan 31 │
│ │ │
│ ← Drag to reschedule → Click bar to see task │
└─────────────────────────────────────────────────────────────────┘
Компоненты:
- Drag & drop scheduling
- Dependency visualization
- Zoom (day/week/month)
- Critical path highlighting
┌─ Project: "Website Redesign" ──────────────────────────────────┐
│ [List] [Board] [Gantt] [Calendar] [Timeline] │
├──────────────────────────────────────────────────────────────────┤
│ January 2026
│ Mo │ Tu │ We │ Th │ Fr │ Sa │ Su │
├────┼────┼────┼────┼────┼────┼────┤
│ 05 │ 06 │ 07 │ 08 │ 09 │ 10 │ 11 │
│ │ │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
│ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │ 18 │
│ │ │ │CSS │Dev │ │ │
│ │ │ │Design Header │ │
│ │ │ │●●●●●●●●●●●●●│ │
├────┼────┼────┼────┼────┼────┼────┤
Компоненты:
- Month/week/day view
- Drag to reschedule
- Multiple events per day
┌─────────────────────────────────────────────────────────────┐
│ TASK-123: Design header [✓ Edit] [⋯ More] │
├─────────────────────────────────────────────────────────────┤
│
│ DESCRIPTION │
│ ┌──────────────────────────────────────────────────────────┐
│ │ Create a modern header component for the new website. │
│ │ Should include logo, nav, and CTA button. │
│ └──────────────────────────────────────────────────────────┘
│
│ PROPERTIES │
│ Status: [In Progress ▼] │
│ Assignees: [●Alice] [+ Add] │
│ Due Date: [Jan 15, 2026] [?] 5 days left │
│ Priority: [High ▼] │
│ Labels: [design] [ui] [+ Add] │
│ Est. Points: [5 ▼] │
│ Parent: [Feature: Website Redesign] │
│
│ ATTACHMENTS (2) │
│ ┌─ wireframe.png (2.3 MB) ........... @Alice Jan 14 │
│ ├─ design-specs.pdf (1.8 MB) ......... @Bob Jan 12 │
│ └─ [+ Upload file] │
│
│ COMMENTS (5) │
│ ┌─────────────────────────────────────────────────────────┐
│ │ @Alice: Design looks great! Just need to add CTA button│
│ │ Jan 14 at 2:45 PM │
│ │ │
│ │ @Bob replied: Added CTA in latest wireframe │
│ │ Jan 14 at 3:20 PM │
│ │ │
│ │ [Write a comment] (@mentions, upload files, send) │
│ └─────────────────────────────────────────────────────────┘
│
│ ACTIVITY (10 items) │
│ Jan 14, 3:20 PM Bob changed status to In Progress │
│ Jan 14, 2:45 PM Alice commented │
│ Jan 12, 1:10 PM Bob attached design-specs.pdf │
│ Jan 12, 12:00 PM Alice assigned task to Bob │
│ Jan 10, 9:30 AM Alice created TASK-123 │
│
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────┐
│ ▶ Workspace: "My Company" │
├─────────────────────────────────────┤
│ │
│ SPACES │
│ ▼ Engineering │
│ ├─ Projects (3) │
│ ├─ My Tasks (5) │
│ ├─ All Tasks │
│ └─ Views (custom) │
│ │
│ ▼ Marketing │
│ ├─ Projects (2) │
│ └─ My Tasks (12) │
│ │
│ ▼ Design │
│ ├─ Projects (1) │
│ └─ My Tasks (8) │
│ │
├─────────────────────────────────────┤
│ SHORTCUTS │
│ ★ Website Redesign │
│ ★ Mobile App (iOS) │
│ ★ Q1 Planning │
├─────────────────────────────────────┤
│ FILTERS │
│ ◉ My Tasks │
│ ○ Assigned to me │
│ ○ Created by me │
│ ○ Watched by me │
├─────────────────────────────────────┤
│ SEARCH │
│ [🔍 Search tasks...] │
│ │
└─────────────────────────────────────┘
<TaskCard
task={task}
onDragStart={handleDragStart}
onClick={() => showDetailModal(task)}
onStatusChange={(newStatus) => updateTask(task.id, newStatus)}
>
<TaskHeader title={task.title} priority={task.priority} />
<TaskAssignees assignees={task.assignees} />
<TaskDueDate dueDate={task.dueDate} overdue={isOverdue} />
<TaskLabels labels={task.labels} />
</TaskCard>
<TaskRow
task={task}
columns={['title', 'status', 'assignee', 'dueDate', 'priority']}
onEdit={(field, value) => updateTask(task.id, { [field]: value })}
onSelect={() => showDetailModal(task)}
/>
<CommentThread taskId={task.id}>
<CommentList comments={comments} onDelete={deleteComment} />
<CommentInput
onMention={(user) => insertMention(user)}
onUpload={(file) => uploadAttachment(file)}
onSubmit={(text) => createComment(text)}
/>
</CommentThread>
<ActivityFeed taskId={task.id}>
{activities.map(activity => (
<ActivityItem
actor={activity.actor}
action={activity.action}
oldValue={activity.oldValue}
newValue={activity.newValue}
timestamp={activity.createdAt}
/>
))}
</ActivityFeed>
[Read mode] → Click field
Title: Design header
[Edit mode] → Type & Save
[🖊️ Design header ... │ ✓ ✕]
→ Save: PATCH /api/tasks/{id}
Current Status: [In Progress ▼]
Popup:
┌─────────────────────┐
│ ○ Backlog │
│ ○ Todo │
│ ● In Progress │
│ ○ In Review │
│ ○ Done │
└─────────────────────┘
Current: [Alice] [Bob] [+ Add]
Popup:
┌──────────────────────────────┐
│ ☑ Alice │
│ ☑ Bob │
│ ☐ Charlie │
│ ☐ Diana │
│ [Filter users...] │
└──────────────────────────────┘
# Projects
GET /api/projects # список
POST /api/projects # создание
GET /api/projects/{id} # детали
PATCH /api/projects/{id} # обновление
DELETE /api/projects/{id} # удаление
# Tasks
GET /api/projects/{projectId}/tasks # список (с фильтрами)
POST /api/projects/{projectId}/tasks # создание
GET /api/tasks/{id} # детали
PATCH /api/tasks/{id} # обновление
DELETE /api/tasks/{id} # удаление
POST /api/tasks/{id}/archive # архивирование
# Comments
GET /api/tasks/{taskId}/comments # список
POST /api/tasks/{taskId}/comments # создание
PATCH /api/comments/{id} # редактирование
DELETE /api/comments/{id} # удаление
# Activity
GET /api/tasks/{taskId}/activity # лог активности
# Attachments
POST /api/tasks/{taskId}/attachments # загрузка
DELETE /api/attachments/{id} # удаление
# Status/Workflow
GET /api/projects/{projectId}/statuses # доступные статусы
POST /api/projects/{projectId}/statuses # создание custom status
# Custom Fields
GET /api/projects/{projectId}/fields # конфиг полей
POST /api/projects/{projectId}/fields # создание
PATCH /api/projects/{projectId}/fields/{id} # обновление
# Фильтрация
GET /api/projects/{projectId}/tasks?status=in_progress&assignee=alice
# Сортировка
GET /api/projects/{projectId}/tasks?sort=dueDate&order=asc
# Паджинация
GET /api/projects/{projectId}/tasks?limit=20&offset=0
# Поиск
GET /api/projects/{projectId}/tasks?search=design&searchFields=title,description
# Включение связанных данных
GET /api/tasks/{id}?include=comments,attachments,activity
# Create Task
mutation CreateTask {
createTask(input: {
projectId: "proj-123"
title: "Design header"
description: "Create modern header component"
assignees: ["user-alice"]
dueDate: "2026-01-15"
priority: "high"
labels: ["design", "ui"]
}) {
id
title
status
createdAt
}
}
# Update Task Status
mutation UpdateTaskStatus {
updateTask(id: "task-123", input: {
status: "in_progress"
}) {
id
status
updatedAt
}
}
# Bulk Update
mutation BulkUpdateTasks {
bulkUpdateTasks(input: {
taskIds: ["task-1", "task-2", "task-3"]
updates: {
assignees: ["user-alice"]
status: "in_progress"
}
}) {
count
updatedAt
}
}