first test

This commit is contained in:
Tomas Dvorak
2026-02-08 14:14:55 +01:00
parent 18aa702174
commit d27cf14110
372 changed files with 98089 additions and 2585 deletions
+193
View File
@@ -0,0 +1,193 @@
package models
import (
"time"
"gorm.io/gorm"
)
// AISummary represents an AI-generated summary
type AISummary struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Source content
ContentType string `json:"content_type" gorm:"not null"` // "bookmark", "note", "file"
ContentID uint `json:"content_id" gorm:"not null"`
// Summary data
Title string `json:"title"`
Summary string `json:"summary" gorm:"type:text"`
KeyPoints string `json:"key_points" gorm:"type:text"` // JSON array of key points
Tags string `json:"tags" gorm:"type:text"` // JSON array of suggested tags
ReadTime int `json:"read_time"` // Estimated reading time in minutes
Complexity string `json:"complexity" gorm:"default:'medium'"` // "low", "medium", "high"
// AI metadata
ModelUsed string `json:"model_used"`
ProcessingMs int64 `json:"processing_ms"`
TokenCount int `json:"token_count"`
Confidence float64 `json:"confidence"` // AI confidence score 0-1
LastAnalyzed time.Time `json:"last_analyzed"`
}
// AITaskSuggestion represents AI-generated task suggestions
type AITaskSuggestion struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Suggestion data
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Priority string `json:"priority" gorm:"default:'medium'"` // "low", "medium", "high", "urgent"
Category string `json:"category"` // "work", "personal", "learning", "health", etc.
// Context and reasoning
Reasoning string `json:"reasoning" gorm:"type:text"` // Why this task is suggested
ContextType string `json:"context_type"` // "calendar", "bookmarks", "deadlines", "habits"
ContextData string `json:"context_data" gorm:"type:text"` // JSON data about context
Deadline *time.Time `json:"deadline"`
EstimatedTime int `json:"estimated_time"` // in minutes
// AI metadata
ModelUsed string `json:"model_used"`
Confidence float64 `json:"confidence"` // AI confidence score 0-1
Accepted bool `json:"accepted" gorm:"default:false"`
Dismissed bool `json:"dismissed" gorm:"default:false"`
}
// AITagSuggestion represents AI-generated tag suggestions
type AITagSuggestion struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Target content
ContentType string `json:"content_type" gorm:"not null"` // "bookmark", "note", "task", "file"
ContentID uint `json:"content_id" gorm:"not null"`
// Tag suggestions
SuggestedTags string `json:"suggested_tags" gorm:"type:text"` // JSON array of suggested tags
ExistingTags string `json:"existing_tags" gorm:"type:text"` // JSON array of current tags
Relevance float64 `json:"relevance"` // Relevance score 0-1
// AI metadata
ModelUsed string `json:"model_used"`
Confidence float64 `json:"confidence"`
Applied bool `json:"applied" gorm:"default:false"`
Dismissed bool `json:"dismissed" gorm:"default:false"`
}
// AIContentGeneration represents AI-generated content
type AIContentGeneration struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Generation request
Prompt string `json:"prompt" gorm:"type:text"`
ContentType string `json:"content_type" gorm:"not null"` // "blog", "code", "email", "summary", "outline"
Context string `json:"context" gorm:"type:text"` // Additional context for generation
// Generated content
Title string `json:"title"`
Content string `json:"content" gorm:"type:text"`
WordCount int `json:"word_count"`
ReadTime int `json:"read_time"` // Estimated reading time in minutes
// AI metadata
ModelUsed string `json:"model_used"`
ProcessingMs int64 `json:"processing_ms"`
TokenCount int `json:"token_count"`
Confidence float64 `json:"confidence"`
Temperature float64 `json:"temperature"`
Used bool `json:"used" gorm:"default:false"`
Rating *int `json:"rating"` // User rating 1-5
Feedback string `json:"feedback" gorm:"type:text"`
}
// AICodeReview represents AI code review analysis
type AICodeReview struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Code context
RepositoryURL string `json:"repository_url"`
CommitHash string `json:"commit_hash"`
FilePath string `json:"file_path"`
PRNumber int `json:"pr_number"`
BranchName string `json:"branch_name"`
// Review data
OriginalCode string `json:"original_code" gorm:"type:text"`
Suggestions string `json:"suggestions" gorm:"type:text"` // JSON array of suggestions
Issues string `json:"issues" gorm:"type:text"` // JSON array of issues found
Score int `json:"score" gorm:"default:0"` // Code quality score 0-100
SecurityIssues string `json:"security_issues" gorm:"type:text"` // JSON array of security issues
Performance string `json:"performance" gorm:"type:text"` // Performance suggestions
// AI metadata
ModelUsed string `json:"model_used"`
Confidence float64 `json:"confidence"`
ProcessingMs int64 `json:"processing_ms"`
TokenCount int `json:"token_count"`
Applied bool `json:"applied" gorm:"default:false"`
}
// AILearningRecommendation represents AI-generated learning recommendations
type AILearningRecommendation struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Recommendation data
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Category string `json:"category"` // "programming", "design", "business", etc.
Difficulty string `json:"difficulty"` // "beginner", "intermediate", "advanced"
EstimatedHours int `json:"estimated_hours"` // Estimated time to complete
Prerequisites string `json:"prerequisites" gorm:"type:text"` // JSON array of prerequisites
Resources string `json:"resources" gorm:"type:text"` // JSON array of learning resources
CourseID *uint `json:"course_id"` // Link to existing course if applicable
// Personalization
Reasoning string `json:"reasoning" gorm:"type:text"` // Why this is recommended
RelevanceScore float64 `json:"relevance_score"` // How relevant to user 0-1
CareerImpact string `json:"career_impact"` // Career impact description
SkillGained string `json:"skill_gained"` // Primary skill gained
// AI metadata
ModelUsed string `json:"model_used"`
Confidence float64 `json:"confidence"`
Started bool `json:"started" gorm:"default:false"`
Completed bool `json:"completed" gorm:"default:false"`
Rating *int `json:"rating"` // User rating 1-5
Feedback string `json:"feedback" gorm:"type:text"`
}
+153
View File
@@ -0,0 +1,153 @@
package models
import (
"time"
"gorm.io/gorm"
)
// AIRecommendation represents an AI-generated recommendation
type AIRecommendation struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// User information
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Recommendation details
RecommendationType string `json:"recommendation_type" gorm:"not null;index"` // content, task, learning, connection
ContentType string `json:"content_type" gorm:"index"` // bookmark, note, task, course, user
ContentID *uint `json:"content_id,omitempty" gorm:"index"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description"`
Reasoning string `json:"reasoning"` // Why this was recommended
// Content details (for display without additional queries)
ContentTitle string `json:"content_title"`
ContentURL string `json:"content_url"`
ContentPreview string `json:"content_preview"`
AuthorName string `json:"author_name"`
Tags string `json:"tags" gorm:"serializer:json"`
// Recommendation metadata
Confidence float64 `json:"confidence" gorm:"default:0.0"` // 0.0 to 1.0
Priority string `json:"priority" gorm:"default:medium"` // low, medium, high
Category string `json:"category"` // productivity, learning, collaboration, etc.
ExpiresAt *time.Time `json:"expires_at"`
Clicked bool `json:"clicked" gorm:"default:false"`
Dismissed bool `json:"dismissed" gorm:"default:false"`
ClickedAt *time.Time `json:"clicked_at"`
DismissedAt *time.Time `json:"dismissed_at"`
// Feedback
Feedback string `json:"feedback"` // helpful, not_helpful, irrelevant
FeedbackAt *time.Time `json:"feedback_at"`
FeedbackText string `json:"feedback_text"`
// Source information
SourceModel string `json:"source_model"` // Which AI model generated this
SourceVersion string `json:"source_version"` // Version of the recommendation engine
TrainingData string `json:"training_data"` // What data was used for training
}
// UserPreference represents user preferences for recommendations
type UserPreference struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// User information
UserID uint `json:"user_id" gorm:"not null;uniqueIndex"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Recommendation preferences
EnableRecommendations bool `json:"enable_recommendations" gorm:"default:true"`
ContentRecommendations bool `json:"content_recommendations" gorm:"default:true"`
TaskRecommendations bool `json:"task_recommendations" gorm:"default:true"`
LearningRecommendations bool `json:"learning_recommendations" gorm:"default:true"`
ConnectionRecommendations bool `json:"connection_recommendations" gorm:"default:false"`
// Frequency and timing
MaxRecommendationsPerDay int `json:"max_recommendations_per_day" gorm:"default:5"`
PreferredCategories []string `json:"preferred_categories" gorm:"serializer:json"`
BlockedCategories []string `json:"blocked_categories" gorm:"serializer:json"`
PreferredContentTypes []string `json:"preferred_content_types" gorm:"serializer:json"`
// Quality thresholds
MinConfidenceThreshold float64 `json:"min_confidence_threshold" gorm:"default:0.6"`
MaxAgeHours int `json:"max_age_hours" gorm:"default:168"` // 1 week
// Learning and adaptation
EnablePersonalization bool `json:"enable_personalization" gorm:"default:true"`
EnableFeedbackLearning bool `json:"enable_feedback_learning" gorm:"default:true"`
LastRecommendationAt *time.Time `json:"last_recommendation_at"`
}
// RecommendationInteraction tracks user interactions with recommendations
type RecommendationInteraction struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Related entities
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
RecommendationID uint `json:"recommendation_id" gorm:"not null;index"`
Recommendation AIRecommendation `json:"recommendation,omitempty" gorm:"foreignKey:RecommendationID"`
// Interaction details
InteractionType string `json:"interaction_type" gorm:"not null;index"` // view, click, dismiss, feedback, share
InteractionData string `json:"interaction_data" gorm:"serializer:json"` // Additional context
Duration int `json:"duration"` // Time spent in seconds (for views)
Context string `json:"context"` // Where the interaction occurred (dashboard, search, etc.)
// Machine learning features
UserActivityBefore string `json:"user_activity_before"` // What user was doing before
UserActivityAfter string `json:"user_activity_after"` // What user did after
SessionID string `json:"session_id"`
DeviceType string `json:"device_type"`
}
// TableName returns the table name for AIRecommendation
func (AIRecommendation) TableName() string {
return "ai_recommendations"
}
// TableName returns the table name for UserPreference
func (UserPreference) TableName() string {
return "user_preferences"
}
// TableName returns the table name for RecommendationInteraction
func (RecommendationInteraction) TableName() string {
return "recommendation_interactions"
}
// BeforeCreate hooks
func (r *AIRecommendation) BeforeCreate(tx *gorm.DB) error {
if r.Priority == "" {
r.Priority = "medium"
}
if r.Confidence == 0 {
r.Confidence = 0.5
}
return nil
}
func (up *UserPreference) BeforeCreate(tx *gorm.DB) error {
if up.MaxRecommendationsPerDay == 0 {
up.MaxRecommendationsPerDay = 5
}
if up.MinConfidenceThreshold == 0 {
up.MinConfidenceThreshold = 0.6
}
if up.MaxAgeHours == 0 {
up.MaxAgeHours = 168 // 1 week
}
return nil
}
+62
View File
@@ -0,0 +1,62 @@
package models
import (
"time"
"gorm.io/gorm"
)
// UserAISettings stores user-specific AI provider configurations
type UserAISettings struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;uniqueIndex"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Mistral Settings
MistralEnabled *bool `json:"mistral_enabled" gorm:"default:false"`
MistralAPIKey string `json:"-" gorm:"column:mistral_api_key"` // Encrypted
MistralModel string `json:"mistral_model" gorm:"default:mistral-small-latest"`
MistralModelThinking string `json:"mistral_model_thinking" gorm:"default:mistral-large-latest"`
// Grok Settings
GrokEnabled *bool `json:"grok_enabled" gorm:"default:false"`
GrokAPIKey string `json:"-" gorm:"column:grok_api_key"` // Encrypted
GrokBaseURL string `json:"grok_base_url" gorm:"default:https://api.x.ai/v1"`
GrokModel string `json:"grok_model" gorm:"default:grok-4-1-fast-non-reasoning-latest"`
GrokModelThinking string `json:"grok_model_thinking" gorm:"default:grok-4-1-fast-reasoning-latest"`
// DeepSeek Settings
DeepSeekEnabled *bool `json:"deepseek_enabled" gorm:"default:false"`
DeepSeekAPIKey string `json:"-" gorm:"column:deepseek_api_key"` // Encrypted
DeepSeekBaseURL string `json:"deepseek_base_url" gorm:"default:https://api.deepseek.com"`
DeepSeekModel string `json:"deepseek_model" gorm:"default:deepseek-chat"`
DeepSeekModelThinking string `json:"deepseek_model_thinking" gorm:"default:deepseek-reasoner"`
// Ollama Settings
OllamaEnabled *bool `json:"ollama_enabled" gorm:"default:false"`
OllamaBaseURL string `json:"ollama_base_url" gorm:"default:http://localhost:11434"`
OllamaModel string `json:"ollama_model" gorm:"default:llama3.1"`
OllamaModelThinking string `json:"ollama_model_thinking" gorm:"default:llama3.1"`
// LongCat Settings
LongCatEnabled *bool `json:"longcat_enabled" gorm:"default:false"`
LongCatAPIKey string `json:"-" gorm:"column:longcat_api_key"` // Encrypted
LongCatBaseURL string `json:"longcat_base_url" gorm:"default:https://api.longcat.chat"`
LongCatOpenAIEndpoint string `json:"longcat_openai_endpoint" gorm:"default:https://api.longcat.chat/openai"`
LongCatAnthropicEndpoint string `json:"longcat_anthropic_endpoint" gorm:"default:https://api.longcat.chat/anthropic"`
LongCatModel string `json:"longcat_model" gorm:"default:LongCat-Flash-Chat"`
LongCatModelThinking string `json:"longcat_model_thinking" gorm:"default:LongCat-Flash-Thinking"`
LongCatModelThinkingUpgraded string `json:"longcat_model_thinking_upgraded" gorm:"default:LongCat-Flash-Thinking-2601"`
LongCatFormat string `json:"longcat_format" gorm:"default:openai"`
// OpenRouter Settings
OpenRouterEnabled *bool `json:"openrouter_enabled" gorm:"default:false"`
OpenRouterAPIKey string `json:"-" gorm:"column:openrouter_api_key"` // Encrypted
OpenRouterBaseURL string `json:"openrouter_base_url" gorm:"default:https://openrouter.ai/api"`
OpenRouterModel string `json:"openrouter_model" gorm:"default:openrouter/auto"`
OpenRouterModelThinking string `json:"openrouter_model_thinking" gorm:"default:openrouter/auto"`
}
+297
View File
@@ -0,0 +1,297 @@
package models
import (
"time"
"gorm.io/gorm"
)
// Analytics represents user analytics data
type Analytics struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Analytics data
Date time.Time `json:"date" gorm:"not null;index"`
HoursTracked float64 `json:"hours_tracked"`
TasksCompleted int `json:"tasks_completed"`
BookmarksAdded int `json:"bookmarks_added"`
NotesCreated int `json:"notes_created"`
CoursesStarted int `json:"courses_started"`
CoursesCompleted int `json:"courses_completed"`
GitHubCommits int `json:"github_commits"`
GitHubPRs int `json:"github_prs"`
StudyStreak int `json:"study_streak"`
ProductivityScore float64 `json:"productivity_score"`
}
// ProductivityMetrics represents productivity analytics
type ProductivityMetrics struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Productivity data
Period string `json:"period"` // daily, weekly, monthly, yearly
StartDate time.Time `json:"start_date"`
EndDate time.Time `json:"end_date"`
TotalHours float64 `json:"total_hours"`
BillableHours float64 `json:"billable_hours"`
NonBillableHours float64 `json:"non_billable_hours"`
TasksCompleted int `json:"tasks_completed"`
AverageTaskTime float64 `json:"average_task_time"`
PeakProductivityHour int `json:"peak_productivity_hour"`
FocusScore float64 `json:"focus_score"`
EfficiencyScore float64 `json:"efficiency_score"`
}
// LearningAnalytics represents learning progress analytics
type LearningAnalytics struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Learning data
CourseID uint `json:"course_id" gorm:"not null;index"`
Course Course `json:"course,omitempty" gorm:"foreignKey:CourseID"`
StartDate time.Time `json:"start_date"`
LastAccessed time.Time `json:"last_accessed"`
TimeSpent float64 `json:"time_spent"` // in hours
Progress float64 `json:"progress"` // percentage 0-100
ModulesCompleted int `json:"modules_completed"`
TotalModules int `json:"total_modules"`
QuizScores []float64 `json:"quiz_scores" gorm:"serializer:json"`
AverageScore float64 `json:"average_score"`
StreakDays int `json:"streak_days"`
SkillsAcquired []string `json:"skills_acquired" gorm:"serializer:json"`
CourseCompleted bool `json:"course_completed" gorm:"default:false"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
}
// ContentAnalytics represents content consumption patterns
type ContentAnalytics struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Content data
ContentType string `json:"content_type"` // bookmark, note, file, task
ContentID uint `json:"content_id"`
FirstAccessed time.Time `json:"first_accessed"`
LastAccessed time.Time `json:"last_accessed"`
AccessCount int `json:"access_count"`
TimeSpent float64 `json:"time_spent"` // in minutes
Tags []Tag `json:"tags,omitempty" gorm:"many2many:content_analytics_tags;"`
Category string `json:"category"`
Priority string `json:"priority"`
UsefulnessScore float64 `json:"usefulness_score"` // user-rated 1-5
}
// GitHubAnalytics represents GitHub contribution analytics
type GitHubAnalytics struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// GitHub data
Date time.Time `json:"date" gorm:"not null;index"`
Commits int `json:"commits"`
PullRequests int `json:"pull_requests"`
IssuesOpened int `json:"issues_opened"`
IssuesClosed int `json:"issues_closed"`
Reviews int `json:"reviews"`
Contributions int `json:"contributions"`
Languages map[string]int `json:"languages" gorm:"serializer:json"`
Repositories []string `json:"repositories" gorm:"serializer:json"`
ActivityScore float64 `json:"activity_score"`
}
// HabitAnalytics represents habit formation insights
type HabitAnalytics struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Habit data
HabitName string `json:"habit_name"`
StartDate time.Time `json:"start_date"`
LastCompleted time.Time `json:"last_completed"`
Streak int `json:"streak"`
BestStreak int `json:"best_streak"`
TotalDays int `json:"total_days"`
CompletionRate float64 `json:"completion_rate"`
Frequency string `json:"frequency"` // daily, weekly, monthly
Category string `json:"category"` // productivity, learning, health, etc.
GoalTarget int `json:"goal_target"`
GoalAchieved bool `json:"goal_achieved"`
}
// Goal represents user goals for tracking
type Goal struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Goal data
Title string `json:"title" gorm:"not null"`
Description string `json:"description"`
Category string `json:"category"` // learning, productivity, health, career
TargetValue float64 `json:"target_value"`
CurrentValue float64 `json:"current_value"`
Unit string `json:"unit"`
Deadline time.Time `json:"deadline"`
Status string `json:"status"` // active, completed, paused, cancelled
Priority string `json:"priority"` // low, medium, high, urgent
Progress float64 `json:"progress"` // percentage 0-100
IsCompleted bool `json:"is_completed" gorm:"default:false"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
// Relationships
Milestones []Milestone `json:"milestones,omitempty" gorm:"foreignKey:GoalID"`
}
// Milestone represents goal milestones
type Milestone struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
GoalID uint `json:"goal_id" gorm:"not null;index"`
Goal Goal `json:"goal,omitempty" gorm:"foreignKey:GoalID"`
// Milestone data
Title string `json:"title" gorm:"not null"`
Description string `json:"description"`
TargetValue float64 `json:"target_value"`
CurrentValue float64 `json:"current_value"`
Deadline time.Time `json:"deadline"`
Status string `json:"status"` // pending, completed, overdue
IsCompleted bool `json:"is_completed" gorm:"default:false"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
Order int `json:"order"`
}
// AnalyticsReport represents a comprehensive analytics report
type AnalyticsReport struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Report data
ReportType string `json:"report_type"` // daily, weekly, monthly, yearly, custom
StartDate time.Time `json:"start_date"`
EndDate time.Time `json:"end_date"`
Title string `json:"title"`
Summary string `json:"summary"`
Data map[string]interface{} `json:"data" gorm:"serializer:json"`
Insights []string `json:"insights" gorm:"serializer:json"`
Recommendations []string `json:"recommendations" gorm:"serializer:json"`
ShareableLink string `json:"shareable_link"`
IsPublic bool `json:"is_public" gorm:"default:false"`
}
// BeforeCreate hooks for default values
func (a *Analytics) BeforeCreate(tx *gorm.DB) error {
if a.Date.IsZero() {
a.Date = time.Now().Truncate(24 * time.Hour)
}
return nil
}
func (p *ProductivityMetrics) BeforeCreate(tx *gorm.DB) error {
if p.StartDate.IsZero() {
p.StartDate = time.Now().Truncate(24 * time.Hour)
}
if p.EndDate.IsZero() {
p.EndDate = p.StartDate.Add(24 * time.Hour)
}
return nil
}
func (l *LearningAnalytics) BeforeCreate(tx *gorm.DB) error {
if l.StartDate.IsZero() {
l.StartDate = time.Now()
}
if l.LastAccessed.IsZero() {
l.LastAccessed = time.Now()
}
return nil
}
func (c *ContentAnalytics) BeforeCreate(tx *gorm.DB) error {
if c.FirstAccessed.IsZero() {
c.FirstAccessed = time.Now()
}
if c.LastAccessed.IsZero() {
c.LastAccessed = time.Now()
}
if c.AccessCount == 0 {
c.AccessCount = 1
}
return nil
}
func (g *GitHubAnalytics) BeforeCreate(tx *gorm.DB) error {
if g.Date.IsZero() {
g.Date = time.Now().Truncate(24 * time.Hour)
}
return nil
}
func (h *HabitAnalytics) BeforeCreate(tx *gorm.DB) error {
if h.StartDate.IsZero() {
h.StartDate = time.Now()
}
return nil
}
func (g *Goal) BeforeCreate(tx *gorm.DB) error {
if g.Status == "" {
g.Status = "active"
}
if g.Priority == "" {
g.Priority = "medium"
}
return nil
}
func (m *Milestone) BeforeCreate(tx *gorm.DB) error {
if m.Status == "" {
m.Status = "pending"
}
return nil
}
+105
View File
@@ -0,0 +1,105 @@
package models
import (
"time"
"gorm.io/gorm"
)
// AuditAction represents the type of action performed
type AuditAction string
const (
AuditActionCreate AuditAction = "create"
AuditActionRead AuditAction = "read"
AuditActionUpdate AuditAction = "update"
AuditActionDelete AuditAction = "delete"
AuditActionLogin AuditAction = "login"
AuditActionLogout AuditAction = "logout"
AuditActionLoginFail AuditAction = "login_failed"
AuditActionExport AuditAction = "export"
AuditActionImport AuditAction = "import"
AuditActionEnable AuditAction = "enable"
AuditActionDisable AuditAction = "disable"
AuditActionUpload AuditAction = "upload"
AuditActionDownload AuditAction = "download"
AuditActionShare AuditAction = "share"
AuditActionAccess AuditAction = "access"
)
// AuditResource represents the resource type
type AuditResource string
const (
AuditResourceUser AuditResource = "user"
AuditResourceNote AuditResource = "note"
AuditResourceFile AuditResource = "file"
AuditResourceBookmark AuditResource = "bookmark"
AuditResourceTask AuditResource = "task"
AuditResourceTimeEntry AuditResource = "time_entry"
AuditResourceIntegration AuditResource = "integration"
AuditResourceTeam AuditResource = "team"
AuditResourceGoal AuditResource = "goal"
AuditResourceHabit AuditResource = "habit"
AuditResourceCalendar AuditResource = "calendar"
AuditResourceSearch AuditResource = "search"
AuditResourceAI AuditResource = "ai"
AuditResourceAnalytics AuditResource = "analytics"
AuditResourceSecurity AuditResource = "security"
AuditResourceSystem AuditResource = "system"
)
// AuditLog represents an audit log entry
type AuditLog struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// User information
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
UserEmail string `json:"user_email" gorm:"not null"`
UserIP string `json:"user_ip"`
UserAgent string `json:"user_agent"`
// Action information
Action AuditAction `json:"action" gorm:"not null;index"`
Resource AuditResource `json:"resource" gorm:"not null;index"`
ResourceID *uint `json:"resource_id,omitempty" gorm:"index"`
// Details
Description string `json:"description"`
Details map[string]interface{} `json:"details" gorm:"serializer:json"`
OldValues map[string]interface{} `json:"old_values" gorm:"serializer:json"`
NewValues map[string]interface{} `json:"new_values" gorm:"serializer:json"`
// Security context
SessionID string `json:"session_id"`
Success bool `json:"success" gorm:"default:true"`
FailureReason string `json:"failure_reason"`
// Geographic and device info
Country string `json:"country"`
City string `json:"city"`
Device string `json:"device"`
Platform string `json:"platform"`
Browser string `json:"browser"`
// Risk assessment
RiskLevel string `json:"risk_level" gorm:"default:low"` // low, medium, high, critical
Suspicious bool `json:"suspicious" gorm:"default:false"`
}
// TableName returns the table name for AuditLog
func (AuditLog) TableName() string {
return "audit_logs"
}
// BeforeCreate hook to set default values
func (a *AuditLog) BeforeCreate(tx *gorm.DB) error {
if a.RiskLevel == "" {
a.RiskLevel = "low"
}
return nil
}
+7 -7
View File
@@ -19,21 +19,21 @@ type Bookmark struct {
Title string `json:"title" gorm:"not null"`
URL string `json:"url" gorm:"not null"`
Description string `json:"description"`
// Organization
Tags []Tag `json:"tags,omitempty" gorm:"many2many:bookmark_tags;"`
Tags []Tag `json:"tags,omitempty" gorm:"many2many:bookmark_tags;"`
// Metadata
Favicon string `json:"favicon"`
Screenshot string `json:"screenshot"`
IsRead bool `json:"is_read" gorm:"default:false"`
IsFavorite bool `json:"is_favorite" gorm:"default:false"`
// Content extraction
Content string `json:"content"`
Author string `json:"author"`
Content string `json:"content"`
Author string `json:"author"`
PublishedAt *time.Time `json:"published_at"`
// Reading tracking
ReadAt *time.Time `json:"read_at"`
}
+170
View File
@@ -0,0 +1,170 @@
package models
import (
"time"
"gorm.io/gorm"
)
// CalendarEvent represents an event in the calendar
type CalendarEvent struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description"`
// Timing
StartTime time.Time `json:"start_time" gorm:"not null"`
EndTime time.Time `json:"end_time" gorm:"not null"`
// Classification
Type string `json:"type" gorm:"default:'reminder'"` // task, meeting, deadline, reminder, habit
Priority string `json:"priority" gorm:"default:'medium'"` // low, medium, high, urgent
// Location and attendees
Location string `json:"location"`
Attendees string `json:"attendees"` // JSON string of attendee emails/names
// Recurrence
Recurring bool `json:"recurring" gorm:"default:false"`
Rrule string `json:"rrule"` // RRULE format for recurrence
// Source integration
Source string `json:"source" gorm:"default:'trackeep'"` // trackeep, google, outlook, manual
// Associations
TaskID *uint `json:"task_id,omitempty"`
Task *Task `json:"task,omitempty" gorm:"foreignKey:TaskID"`
BookmarkID *uint `json:"bookmark_id,omitempty"`
Bookmark *Bookmark `json:"bookmark,omitempty" gorm:"foreignKey:BookmarkID"`
NoteID *uint `json:"note_id,omitempty"`
Note *Note `json:"note,omitempty" gorm:"foreignKey:NoteID"`
// Status
IsCompleted bool `json:"is_completed" gorm:"default:false"`
IsAllDay bool `json:"is_all_day" gorm:"default:false"`
// Notifications
ReminderMinutes int `json:"reminder_minutes"` // Minutes before event to remind
}
// RecurrenceRule represents recurrence patterns for events
type RecurrenceRule struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
Frequency string `json:"frequency" gorm:"not null"` // daily, weekly, monthly, yearly
Interval int `json:"interval" gorm:"default:1"` // Every N days/weeks/months/years
// End conditions
EndDate *time.Time `json:"end_date"`
Count *int `json:"count"` // Number of occurrences
IsForever bool `json:"is_forever" gorm:"default:false"`
// Weekly specifics
DaysOfWeek string `json:"days_of_week"` // JSON array: [0,1,2,3,4,5,6] where 0=Sunday
// Monthly specifics
DayOfMonth *int `json:"day_of_month"` // 1-31
WeekOfMonth *int `json:"week_of_month"` // 1-5 (first to fifth week)
DayOfWeek *int `json:"day_of_week"` // 0-6 (Sunday to Saturday)
// Event association
EventID uint `json:"event_id" gorm:"not null"`
Event CalendarEvent `json:"event,omitempty" gorm:"foreignKey:EventID"`
}
// CalendarSettings represents user calendar preferences
type CalendarSettings struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;uniqueIndex"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Display preferences
DefaultView string `json:"default_view" gorm:"default:'week'"` // month, week, day
WeekStartsOn int `json:"week_starts_on" gorm:"default:0"` // 0=Sunday, 1=Monday
Timezone string `json:"timezone" gorm:"default:'UTC'"`
TimeFormat24Hour bool `json:"time_format_24_hour" gorm:"default:true"`
// Integration settings
GoogleCalendarEnabled bool `json:"google_calendar_enabled" gorm:"default:false"`
GoogleCalendarToken string `json:"google_calendar_token"`
OutlookEnabled bool `json:"outlook_enabled" gorm:"default:false"`
OutlookToken string `json:"outlook_token"`
// Notification settings
DefaultReminderMinutes int `json:"default_reminder_minutes" gorm:"default:15"`
EmailRemindersEnabled bool `json:"email_reminders_enabled" gorm:"default:true"`
PushRemindersEnabled bool `json:"push_reminders_enabled" gorm:"default:true"`
}
// GetDuration returns the duration of the event
func (e *CalendarEvent) GetDuration() time.Duration {
return e.EndTime.Sub(e.StartTime)
}
// IsOverdue checks if the event is overdue
func (e *CalendarEvent) IsOverdue() bool {
return !e.IsCompleted && time.Now().After(e.EndTime)
}
// IsToday checks if the event occurs today
func (e *CalendarEvent) IsToday() bool {
now := time.Now()
return e.StartTime.Year() == now.Year() &&
e.StartTime.Month() == now.Month() &&
e.StartTime.Day() == now.Day()
}
// IsUpcoming checks if the event is in the next 7 days
func (e *CalendarEvent) IsUpcoming() bool {
now := time.Now()
weekLater := now.AddDate(0, 0, 7)
return e.StartTime.After(now) && e.StartTime.Before(weekLater)
}
// GetPriorityColor returns a color based on priority
func (e *CalendarEvent) GetPriorityColor() string {
switch e.Priority {
case "urgent":
return "#ef4444" // red
case "high":
return "#f97316" // orange
case "medium":
return "#eab308" // yellow
case "low":
return "#22c55e" // green
default:
return "#6b7280" // gray
}
}
// GetTypeColor returns a color based on event type
func (e *CalendarEvent) GetTypeColor() string {
switch e.Type {
case "task":
return "#3b82f6" // blue
case "meeting":
return "#8b5cf6" // purple
case "deadline":
return "#ef4444" // red
case "reminder":
return "#06b6d4" // cyan
case "habit":
return "#10b981" // emerald
default:
return "#6b7280" // gray
}
}
+56
View File
@@ -0,0 +1,56 @@
package models
import (
"time"
"gorm.io/gorm"
)
// ChatMessage represents a chat message in the AI conversation
type ChatMessage struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Content string `json:"content" gorm:"not null"`
Role string `json:"role" gorm:"not null"` // "user" or "assistant"
// Session tracking
SessionID string `json:"session_id" gorm:"not null;index"`
// Metadata
TokenCount int `json:"token_count"`
ModelUsed string `json:"model_used"`
ProcessingMs int64 `json:"processing_ms"`
ContextItems []string `json:"context_items" gorm:"serializer:json"` // IDs of referenced items
}
// ChatSession represents a chat session
type ChatSession struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Title string `json:"title"`
// Session metadata
MessageCount int `json:"message_count" gorm:"default:0"`
LastMessageAt *time.Time `json:"last_message_at"`
// Context configuration
IncludeBookmarks bool `json:"include_bookmarks" gorm:"default:true"`
IncludeTasks bool `json:"include_tasks" gorm:"default:true"`
IncludeFiles bool `json:"include_files" gorm:"default:true"`
IncludeNotes bool `json:"include_notes" gorm:"default:true"`
// Relationships
Messages []ChatMessage `json:"messages,omitempty" gorm:"foreignKey:SessionID"`
}
+444
View File
@@ -0,0 +1,444 @@
package models
import (
"time"
"gorm.io/gorm"
)
// Challenge represents a community challenge
type Challenge struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Creator information
CreatorID uint `json:"creator_id" gorm:"not null;index"`
Creator User `json:"creator,omitempty" gorm:"foreignKey:CreatorID"`
// Basic information
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Category string `json:"category" gorm:"not null"` // learning, productivity, fitness, creativity, technical
// Challenge details
Difficulty string `json:"difficulty" gorm:"not null"` // beginner, intermediate, advanced, expert
Duration int `json:"duration" gorm:"not null"` // Duration in days
Requirements string `json:"requirements" gorm:"type:text"`
Rewards string `json:"rewards" gorm:"type:text"`
Rules string `json:"rules" gorm:"type:text"`
// Timeline
StartDate time.Time `json:"start_date"`
EndDate time.Time `json:"end_date"`
// Participation settings
MaxParticipants *int `json:"max_participants,omitempty"` // nil for unlimited
IsTeamChallenge bool `json:"is_team_challenge" gorm:"default:false"`
TeamSize int `json:"team_size" gorm:"default:1"`
// Status and visibility
Status string `json:"status" gorm:"default:draft"` // draft, active, completed, cancelled
IsPublic bool `json:"is_public" gorm:"default:true"`
IsFeatured bool `json:"is_featured" gorm:"default:false"`
// Tags and metadata
Tags []ChallengeTag `json:"tags,omitempty" gorm:"many2many:challenge_tags;"`
Image string `json:"image"` // Challenge banner/image
Badge string `json:"badge"` // Completion badge
// Analytics
ParticipantCount int `json:"participant_count" gorm:"default:0"`
CompletionCount int `json:"completion_count" gorm:"default:0"`
CompletionRate float64 `json:"completion_rate" gorm:"default:0"`
LastActivityAt *time.Time `json:"last_activity_at,omitempty"`
// Relationships
Participants []ChallengeParticipant `json:"participants,omitempty" gorm:"foreignKey:ChallengeID"`
Milestones []ChallengeMilestone `json:"milestones,omitempty" gorm:"foreignKey:ChallengeID"`
Resources []ChallengeResource `json:"resources,omitempty" gorm:"foreignKey:ChallengeID"`
}
// ChallengeParticipant represents a user's participation in a challenge
type ChallengeParticipant struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Participation information
ChallengeID uint `json:"challenge_id" gorm:"not null;index"`
Challenge Challenge `json:"challenge,omitempty" gorm:"foreignKey:ChallengeID"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Team information (for team challenges)
TeamID *uint `json:"team_id,omitempty"`
Team *ChallengeTeam `json:"team,omitempty" gorm:"foreignKey:TeamID"`
Role string `json:"role" gorm:"default:participant"` // participant, team_leader
// Progress tracking
Status string `json:"status" gorm:"default:joined"` // joined, in_progress, completed, dropped_out
Progress float64 `json:"progress" gorm:"default:0"` // Progress percentage (0-100)
StartedAt *time.Time `json:"started_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
DroppedOutAt *time.Time `json:"dropped_out_at,omitempty"`
// Performance metrics
Score int `json:"score" gorm:"default:0"`
Rank int `json:"rank"`
BadgeEarned bool `json:"badge_earned" gorm:"default:false"`
LastActivityAt *time.Time `json:"last_activity_at,omitempty"`
// Notes and reflection
Notes string `json:"notes" gorm:"type:text"`
Reflection string `json:"reflection" gorm:"type:text"`
}
// ChallengeTeam represents a team in a team challenge
type ChallengeTeam struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Team information
ChallengeID uint `json:"challenge_id" gorm:"not null;index"`
Challenge Challenge `json:"challenge,omitempty" gorm:"foreignKey:ChallengeID"`
Name string `json:"name" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Avatar string `json:"avatar"`
// Team settings
IsPrivate bool `json:"is_private" gorm:"default:false"`
MaxMembers int `json:"max_members" gorm:"default:5"`
// Team progress
Status string `json:"status" gorm:"default:active"` // active, completed, disbanded
Progress float64 `json:"progress" gorm:"default:0"`
Score int `json:"score" gorm:"default:0"`
Rank int `json:"rank"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
LastActivityAt *time.Time `json:"last_activity_at,omitempty"`
// Relationships
LeaderID uint `json:"leader_id" gorm:"not null"`
Leader User `json:"leader,omitempty" gorm:"foreignKey:LeaderID"`
Members []ChallengeParticipant `json:"members,omitempty" gorm:"foreignKey:TeamID"`
}
// ChallengeMilestone represents a milestone in a challenge
type ChallengeMilestone struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Milestone information
ChallengeID uint `json:"challenge_id" gorm:"not null;index"`
Challenge Challenge `json:"challenge,omitempty" gorm:"foreignKey:ChallengeID"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
// Milestone details
Order int `json:"order" gorm:"not null"` // Order in the challenge
TargetValue float64 `json:"target_value" gorm:"not null"`
Unit string `json:"unit"` // days, points, hours, etc.
Deadline time.Time `json:"deadline"`
PointsAwarded int `json:"points_awarded" gorm:"default:0"`
// Status
IsActive bool `json:"is_active" gorm:"default:true"`
// Relationships
Completions []ChallengeMilestoneCompletion `json:"completions,omitempty" gorm:"foreignKey:MilestoneID"`
}
// ChallengeMilestoneCompletion represents a user's completion of a milestone
type ChallengeMilestoneCompletion struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Completion information
MilestoneID uint `json:"milestone_id" gorm:"not null;index"`
Milestone ChallengeMilestone `json:"milestone,omitempty" gorm:"foreignKey:MilestoneID"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
TeamID *uint `json:"team_id,omitempty"`
// Completion details
CompletedAt time.Time `json:"completed_at"`
Notes string `json:"notes" gorm:"type:text"`
Evidence string `json:"evidence" gorm:"type:text"` // Proof of completion
PointsEarned int `json:"points_earned"`
}
// ChallengeResource represents a resource for a challenge
type ChallengeResource struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Resource information
ChallengeID uint `json:"challenge_id" gorm:"not null;index"`
Challenge Challenge `json:"challenge,omitempty" gorm:"foreignKey:ChallengeID"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
URL string `json:"url"`
Type string `json:"type" gorm:"not null"` // article, video, tool, template, guide
// Resource details
Order int `json:"order" gorm:"default:0"`
IsRequired bool `json:"is_required" gorm:"default:false"`
Duration int `json:"duration"` // Estimated duration in minutes
Tags string `json:"tags"` // Comma-separated tags
}
// ChallengeTag represents tags for challenges
type ChallengeTag struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
Name string `json:"name" gorm:"uniqueIndex;not null"`
Description string `json:"description"`
Color string `json:"color" gorm:"default:#10b981"` // Tag color
UsageCount int `json:"usage_count" gorm:"default:0"`
}
// Mentorship represents a mentorship relationship
type Mentorship struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Participants
MentorID uint `json:"mentor_id" gorm:"not null;index"`
Mentor User `json:"mentor,omitempty" gorm:"foreignKey:MentorID"`
MenteeID uint `json:"mentee_id" gorm:"not null;index"`
Mentee User `json:"mentee,omitempty" gorm:"foreignKey:MenteeID"`
// Mentorship details
Category string `json:"category" gorm:"not null"` // career, technical, business, personal
Description string `json:"description" gorm:"type:text"`
Goals string `json:"goals" gorm:"type:text"`
// Timeline
StartDate time.Time `json:"start_date"`
EndDate *time.Time `json:"end_date,omitempty"`
// Status and settings
Status string `json:"status" gorm:"default:pending"` // pending, active, paused, completed, terminated
IsPaid bool `json:"is_paid" gorm:"default:false"`
Rate float64 `json:"rate" gorm:"default:0"` // Hourly rate or monthly rate
Currency string `json:"currency" gorm:"default:USD"`
SessionLimit int `json:"session_limit" gorm:"default:0"` // 0 for unlimited
// Matching preferences
MentorPreferences string `json:"mentor_preferences" gorm:"type:text"`
MenteePreferences string `json:"mentee_preferences" gorm:"type:text"`
// Analytics
SessionCount int `json:"session_count" gorm:"default:0"`
TotalHours float64 `json:"total_hours" gorm:"default:0"`
LastSessionAt *time.Time `json:"last_session_at,omitempty"`
SatisfactionScore float64 `json:"satisfaction_score" gorm:"default:0"` // 1-5 rating
// Relationships
Sessions []MentorshipSession `json:"sessions,omitempty" gorm:"foreignKey:MentorshipID"`
Reviews []MentorshipReview `json:"reviews,omitempty" gorm:"foreignKey:MentorshipID"`
Milestones []MentorshipMilestone `json:"milestones,omitempty" gorm:"foreignKey:MentorshipID"`
}
// MentorshipSession represents a mentoring session
type MentorshipSession struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Session information
MentorshipID uint `json:"mentorship_id" gorm:"not null;index"`
Mentorship Mentorship `json:"mentorship,omitempty" gorm:"foreignKey:MentorshipID"`
ScheduledFor time.Time `json:"scheduled_for"`
Duration int `json:"duration"` // Duration in minutes
Status string `json:"status" gorm:"default:scheduled"` // scheduled, completed, cancelled, no_show
// Session details
Title string `json:"title"`
Agenda string `json:"agenda" gorm:"type:text"`
Notes string `json:"notes" gorm:"type:text"`
RecordingURL string `json:"recording_url"`
Materials string `json:"materials" gorm:"type:text"`
// Completion details
CompletedAt *time.Time `json:"completed_at,omitempty"`
MentorNotes string `json:"mentor_notes" gorm:"type:text"`
MenteeNotes string `json:"mentee_notes" gorm:"type:text"`
ActionItems string `json:"action_items" gorm:"type:text"`
NextSteps string `json:"next_steps" gorm:"type:text"`
// Feedback
MentorRating *int `json:"mentor_rating,omitempty"` // 1-5 rating from mentee
MenteeRating *int `json:"mentee_rating,omitempty"` // 1-5 rating from mentor
MentorFeedback string `json:"mentor_feedback" gorm:"type:text"`
MenteeFeedback string `json:"mentee_feedback" gorm:"type:text"`
}
// MentorshipReview represents a review for a mentorship
type MentorshipReview struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Review information
MentorshipID uint `json:"mentorship_id" gorm:"not null;index"`
Mentorship Mentorship `json:"mentorship,omitempty" gorm:"foreignKey:MentorshipID"`
ReviewerID uint `json:"reviewer_id" gorm:"not null;index"`
Reviewer User `json:"reviewer,omitempty" gorm:"foreignKey:ReviewerID"`
TargetID uint `json:"target_id" gorm:"not null;index"` // The person being reviewed
Target User `json:"target,omitempty" gorm:"foreignKey:TargetID"`
// Review content
Rating int `json:"rating" gorm:"not null;check:rating >= 1 AND rating <= 5"` // 1-5 stars
Title string `json:"title"`
Content string `json:"content" gorm:"type:text"`
IsPublic bool `json:"is_public" gorm:"default:false"`
IsVerified bool `json:"is_verified" gorm:"default:false"` // Verified mentorship
// Review metadata
HelpfulCount int `json:"helpful_count" gorm:"default:0"`
ReviewType string `json:"review_type" gorm:"not null"` // mentor_review, mentee_review
}
// MentorshipMilestone represents a milestone in a mentorship
type MentorshipMilestone struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Milestone information
MentorshipID uint `json:"mentorship_id" gorm:"not null;index"`
Mentorship Mentorship `json:"mentorship,omitempty" gorm:"foreignKey:MentorshipID"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
// Milestone details
TargetDate time.Time `json:"target_date"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
Status string `json:"status" gorm:"default:pending"` // pending, completed, overdue
Priority string `json:"priority" gorm:"default:medium"` // low, medium, high
// Progress tracking
Progress float64 `json:"progress" gorm:"default:0"` // 0-100
Evidence string `json:"evidence" gorm:"type:text"`
Notes string `json:"notes" gorm:"type:text"`
}
// MentorshipRequest represents a mentorship request
type MentorshipRequest struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Request information
FromUserID uint `json:"from_user_id" gorm:"not null;index"`
FromUser User `json:"from_user,omitempty" gorm:"foreignKey:FromUserID"`
ToUserID uint `json:"to_user_id" gorm:"not null;index"`
ToUser User `json:"to_user,omitempty" gorm:"foreignKey:ToUserID"`
// Request details
Role string `json:"role" gorm:"not null"` // mentor, mentee
Category string `json:"category" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Goals string `json:"goals" gorm:"type:text"`
Availability string `json:"availability" gorm:"type:text"`
Duration int `json:"duration"` // Desired duration in months
IsPaid bool `json:"is_paid"`
Rate float64 `json:"rate"`
Currency string `json:"currency" gorm:"default:USD"`
// Status
Status string `json:"status" gorm:"default:pending"` // pending, accepted, rejected, withdrawn
RespondedAt *time.Time `json:"responded_at,omitempty"`
Response string `json:"response" gorm:"type:text"`
// Matching score (calculated by matching algorithm)
MatchScore float64 `json:"match_score" gorm:"default:0"`
MatchReasons string `json:"match_reasons" gorm:"type:text"`
}
// BeforeCreate hooks
func (c *Challenge) BeforeCreate(tx *gorm.DB) error {
if c.Status == "" {
c.Status = "draft"
}
return nil
}
func (cp *ChallengeParticipant) BeforeCreate(tx *gorm.DB) error {
if cp.Status == "" {
cp.Status = "joined"
}
return nil
}
func (ct *ChallengeTeam) BeforeCreate(tx *gorm.DB) error {
if ct.Status == "" {
ct.Status = "active"
}
return nil
}
func (m *Mentorship) BeforeCreate(tx *gorm.DB) error {
if m.Status == "" {
m.Status = "pending"
}
if m.Currency == "" {
m.Currency = "USD"
}
return nil
}
func (ms *MentorshipSession) BeforeCreate(tx *gorm.DB) error {
if ms.Status == "" {
ms.Status = "scheduled"
}
return nil
}
func (mr *MentorshipReview) BeforeCreate(tx *gorm.DB) error {
if mr.ReviewType == "" {
mr.ReviewType = "mentor_review"
}
return nil
}
func (mm *MentorshipMilestone) BeforeCreate(tx *gorm.DB) error {
if mm.Status == "" {
mm.Status = "pending"
}
if mm.Priority == "" {
mm.Priority = "medium"
}
return nil
}
func (mr *MentorshipRequest) BeforeCreate(tx *gorm.DB) error {
if mr.Status == "" {
mr.Status = "pending"
}
if mr.Currency == "" {
mr.Currency = "USD"
}
return nil
}
+69
View File
@@ -0,0 +1,69 @@
package models
import (
"time"
"gorm.io/gorm"
)
// Course represents a Zero to Mastery course
type Course struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Basic course information
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Slug string `json:"slug" gorm:"uniqueIndex;not null"` // URL-friendly course identifier
URL string `json:"url" gorm:"not null"` // ZTM course URL
Thumbnail string `json:"thumbnail"`
Instructor string `json:"instructor"`
// Course metadata
Duration string `json:"duration"` // e.g., "32 Hours"
LessonsCount int `json:"lessons_count"` // number of lessons
ModuleCount int `json:"module_count"` // number of modules
Level string `json:"level"` // beginner, intermediate, advanced
Category string `json:"category"` // programming, design, cybersecurity, etc.
Price float64 `json:"price"` // course price
Rating float64 `json:"rating"` // average rating
StudentsCount int `json:"students_count"` // number of enrolled students
// Course content
Prerequisites []string `json:"prerequisites" gorm:"serializer:json"`
WhatYouLearn []string `json:"what_you_learn" gorm:"serializer:json"`
Topics []string `json:"topics" gorm:"serializer:json"`
ToolsAndTech []string `json:"tools_and_tech" gorm:"serializer:json"`
// ZTM specific data
ZTMCourseID string `json:"ztm_course_id"` // internal ZTM course ID
ZTMCategory string `json:"ztm_category"` // ZTM category classification
IsZTMCourse bool `json:"is_ztm_course" gorm:"default:true"`
LastUpdatedZTM *time.Time `json:"last_updated_ztm"` // last sync with ZTM
// Status
IsActive bool `json:"is_active" gorm:"default:true"`
IsFeatured bool `json:"is_featured" gorm:"default:false"`
}
// LearningPathCourse represents the relationship between learning paths and courses
type LearningPathCourse struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
LearningPathID uint `json:"learning_path_id" gorm:"not null;index"`
LearningPath LearningPath `json:"learning_path,omitempty" gorm:"foreignKey:LearningPathID"`
CourseID uint `json:"course_id" gorm:"not null;index"`
Course Course `json:"course,omitempty" gorm:"foreignKey:CourseID"`
// Relationship metadata
Order int `json:"order" gorm:"not null"` // order in the learning path
IsRequired bool `json:"is_required" gorm:"default:true"` // whether this course is required
Notes string `json:"notes" gorm:"type:text"` // additional notes about why this course is included
EstimatedWeeks int `json:"estimated_weeks"` // estimated weeks to complete this course
}
+15 -11
View File
@@ -28,24 +28,28 @@ type File struct {
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
OriginalName string `json:"original_name" gorm:"not null"`
FileName string `json:"file_name" gorm:"not null;uniqueIndex"`
FilePath string `json:"file_path" gorm:"not null"`
FileSize int64 `json:"file_size" gorm:"not null"`
MimeType string `json:"mime_type" gorm:"not null"`
FileType FileType `json:"file_type" gorm:"not null"`
OriginalName string `json:"original_name" gorm:"not null"`
FileName string `json:"file_name" gorm:"not null;uniqueIndex"`
FilePath string `json:"file_path" gorm:"not null"`
FileSize int64 `json:"file_size" gorm:"not null"`
MimeType string `json:"mime_type" gorm:"not null"`
FileType FileType `json:"file_type" gorm:"not null"`
// Encryption
IsEncrypted bool `json:"is_encrypted" gorm:"default:false"`
EncryptionKey string `json:"-" gorm:"column:encryption_key"` // User-specific encryption key (optional)
// Organization
Tags []Tag `json:"tags,omitempty" gorm:"many2many:file_tags;"`
// Metadata
Description string `json:"description"`
IsPublic bool `json:"is_public" gorm:"default:false"`
IsPublic bool `json:"is_public" gorm:"default:false"`
// Preview/Thumbnail
ThumbnailPath string `json:"thumbnail_path"`
PreviewPath string `json:"preview_path"`
// Content extraction (for documents)
Content string `json:"content"`
}
+52
View File
@@ -0,0 +1,52 @@
package models
import (
"time"
"gorm.io/gorm"
)
// FileAnalysis represents analysis results for a file
type FileAnalysis struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// File information
FileID uint `json:"file_id" gorm:"not null;uniqueIndex:idx_file_analysis_type"`
File File `json:"file,omitempty" gorm:"foreignKey:FileID"`
AnalysisType string `json:"analysis_type" gorm:"not null;uniqueIndex:idx_file_analysis_type"` // computer_vision, nlp, metadata
// Analysis results
Results string `json:"results" gorm:"type:text"` // JSON-encoded analysis results
Confidence float64 `json:"confidence" gorm:"default:0.0"` // 0.0 to 1.0
Status string `json:"status" gorm:"default:pending"` // pending, processing, completed, failed
// Processing metadata
ProcessedAt *time.Time `json:"processed_at"`
ProcessingTime int `json:"processing_time"` // in milliseconds
ModelVersion string `json:"model_version"` // AI model version used
Error string `json:"error"` // Error message if failed
// Additional metadata
Tags string `json:"tags" gorm:"serializer:json"`
Metadata string `json:"metadata" gorm:"serializer:json"`
ExtractedData string `json:"extracted_data" gorm:"type:text"` // Extracted text, objects, etc.
}
// TableName returns the table name for FileAnalysis
func (FileAnalysis) TableName() string {
return "file_analyses"
}
// BeforeCreate hook to set default values
func (fa *FileAnalysis) BeforeCreate(tx *gorm.DB) error {
if fa.Status == "" {
fa.Status = "pending"
}
if fa.Confidence == 0 {
fa.Confidence = 0.0
}
return nil
}
+173
View File
@@ -0,0 +1,173 @@
package models
import (
"time"
"gorm.io/gorm"
)
// Habit represents a habit that can be tracked
type Habit struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Basic habit information
Name string `json:"name" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Category string `json:"category" gorm:"default:personal"` // health, productivity, learning, personal
// Habit tracking
TargetFrequency int `json:"target_frequency"` // e.g., 7 times per week
FrequencyUnit string `json:"frequency_unit"` // daily, weekly, monthly
TargetValue float64 `json:"target_value"` // e.g., 30 minutes, 8 glasses
Unit string `json:"unit"` // minutes, glasses, pages, etc.
// Schedule
TimeOfDay string `json:"time_of_day"` // morning, afternoon, evening, night
DaysOfWeek []string `json:"days_of_week" gorm:"serializer:json"` // ["monday", "tuesday", etc.]
// Status and settings
IsActive bool `json:"is_active" gorm:"default:true"`
IsPublic bool `json:"is_public" gorm:"default:false"`
Streak int `json:"streak" gorm:"default:0"`
LongestStreak int `json:"longest_streak" gorm:"default:0"`
CompletionRate float64 `json:"completion_rate" gorm:"default:0"` // percentage
// Relationships
GoalID *uint `json:"goal_id,omitempty"`
Goal *Goal `json:"goal,omitempty" gorm:"foreignKey:GoalID"`
HabitEntries []HabitEntry `json:"habit_entries,omitempty" gorm:"foreignKey:HabitID"`
HabitTags []HabitTag `json:"habit_tags,omitempty" gorm:"foreignKey:HabitID"`
}
// HabitEntry represents a single completion of a habit
type HabitEntry struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
HabitID uint `json:"habit_id" gorm:"not null;index"`
Habit Habit `json:"habit,omitempty" gorm:"foreignKey:HabitID"`
EntryDate time.Time `json:"entry_date" gorm:"not null;index"`
Value float64 `json:"value"` // actual value completed
TargetValue float64 `json:"target_value"` // target value for this entry
Unit string `json:"unit"`
Notes string `json:"notes" gorm:"type:text"`
IsCompleted bool `json:"is_completed" gorm:"default:false"`
Quality int `json:"quality" gorm:"default:3"` // 1-5 rating
TimeSpent int `json:"time_spent"` // minutes spent
Location string `json:"location"`
Mood string `json:"mood"` // happy, neutral, stressed, etc.
}
// GoalTag represents tags for goals
type GoalTag struct {
ID uint `json:"id" gorm:"primaryKey"`
GoalID uint `json:"goal_id" gorm:"not null;index"`
TagID uint `json:"tag_id" gorm:"not null;index"`
Goal Goal `json:"goal,omitempty" gorm:"foreignKey:GoalID"`
Tag Tag `json:"tag,omitempty" gorm:"foreignKey:TagID"`
}
// HabitTag represents tags for habits
type HabitTag struct {
ID uint `json:"id" gorm:"primaryKey"`
HabitID uint `json:"habit_id" gorm:"not null;index"`
TagID uint `json:"tag_id" gorm:"not null;index"`
Habit Habit `json:"habit,omitempty" gorm:"foreignKey:HabitID"`
Tag Tag `json:"tag,omitempty" gorm:"foreignKey:TagID"`
}
// GoalTemplate represents templates for creating goals
type GoalTemplate struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
Name string `json:"name" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Category string `json:"category"`
Unit string `json:"unit"`
TargetValue float64 `json:"target_value"`
Duration int `json:"duration"` // suggested duration in days
IsPublic bool `json:"is_public" gorm:"default:false"`
UsageCount int `json:"usage_count" gorm:"default:0"`
// Template milestones
Milestones []GoalTemplateMilestone `json:"milestones,omitempty" gorm:"foreignKey:GoalTemplateID"`
}
// GoalTemplateMilestone represents milestones in goal templates
type GoalTemplateMilestone struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
GoalTemplateID uint `json:"goal_template_id" gorm:"not null;index"`
GoalTemplate GoalTemplate `json:"goal_template,omitempty" gorm:"foreignKey:GoalTemplateID"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
TargetValue float64 `json:"target_value"`
Unit string `json:"unit"`
DayOffset int `json:"day_offset"` // days from start date
SortOrder int `json:"sort_order" gorm:"default:0"`
}
// BeforeCreate hooks
func (h *Habit) BeforeCreate(tx *gorm.DB) error {
if h.Category == "" {
h.Category = "personal"
}
if h.FrequencyUnit == "" {
h.FrequencyUnit = "daily"
}
return nil
}
func (he *HabitEntry) BeforeCreate(tx *gorm.DB) error {
// Set completion based on value vs target
if he.Value >= he.TargetValue {
he.IsCompleted = true
}
return nil
}
// BeforeUpdate hooks
func (h *Habit) BeforeUpdate(tx *gorm.DB) error {
// Update completion rate and streak
h.updateStreakAndRate()
return nil
}
// Helper methods
// updateStreakAndRate calculates current streak and completion rate
func (h *Habit) updateStreakAndRate() {
// This would typically involve querying habit entries
// For now, we'll keep the existing values
// In a real implementation, you'd calculate based on recent entries
}
// GetTodayEntry gets today's habit entry if it exists
func (h *Habit) GetTodayEntry() *HabitEntry {
// This would typically query the database
// For now, return nil
return nil
}
// GetWeeklyStreak gets the current weekly streak
func (h *Habit) GetWeeklyStreak() int {
// This would calculate based on habit entries
// For now, return the stored streak
return h.Streak
}
+293
View File
@@ -0,0 +1,293 @@
package models
import (
"time"
"gorm.io/gorm"
)
// IntegrationType represents the type of integration
type IntegrationType string
const (
IntegrationSlack IntegrationType = "slack"
IntegrationDiscord IntegrationType = "discord"
IntegrationNotion IntegrationType = "notion"
IntegrationPocket IntegrationType = "pocket"
IntegrationTodoist IntegrationType = "todoist"
IntegrationGoogle IntegrationType = "google"
IntegrationGitHub IntegrationType = "github"
IntegrationTwitter IntegrationType = "twitter"
IntegrationReddit IntegrationType = "reddit"
IntegrationObsidian IntegrationType = "obsidian"
)
// IntegrationStatus represents the status of an integration
type IntegrationStatus string
const (
StatusActive IntegrationStatus = "active"
StatusInactive IntegrationStatus = "inactive"
StatusError IntegrationStatus = "error"
StatusPending IntegrationStatus = "pending"
)
// Integration represents a third-party service integration
type Integration struct {
ID string `json:"id" gorm:"primaryKey;type:uuid;default:gen_random_uuid()"`
UserID string `json:"userId" gorm:"not null;index;type:uuid"`
Type IntegrationType `json:"type" gorm:"not null;index"`
Status IntegrationStatus `json:"status" gorm:"not null;default:'pending'"`
Name string `json:"name" gorm:"not null"`
Description string `json:"description"`
// Configuration stored as JSON
Config IntegrationConfig `json:"config" gorm:"type:jsonb"`
// Authentication tokens (encrypted)
AccessToken string `json:"-" gorm:"type:text"` // Encrypted
RefreshToken string `json:"-" gorm:"type:text"` // Encrypted
// Sync settings
SyncEnabled bool `json:"syncEnabled" gorm:"default:true"`
LastSyncAt *time.Time `json:"lastSyncAt"`
SyncInterval int `json:"syncInterval"` // in minutes, 0 = manual
// Webhook settings
WebhookURL string `json:"webhookUrl" gorm:"type:text"`
WebhookSecret string `json:"-" gorm:"type:text"` // Encrypted
// Statistics
SyncCount int `json:"syncCount" gorm:"default:0"`
ErrorCount int `json:"errorCount" gorm:"default:0"`
LastError string `json:"lastError" gorm:"type:text"`
// Timestamps
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Relationships
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
SyncLogs []SyncLog `json:"syncLogs,omitempty" gorm:"foreignKey:IntegrationID"`
}
// IntegrationConfig holds configuration specific to each integration type
type IntegrationConfig struct {
// Slack configuration
SlackConfig *SlackConfig `json:"slackConfig,omitempty"`
// Discord configuration
DiscordConfig *DiscordConfig `json:"discordConfig,omitempty"`
// Notion configuration
NotionConfig *NotionConfig `json:"notionConfig,omitempty"`
// Google configuration
GoogleConfig *GoogleConfig `json:"googleConfig,omitempty"`
// Pocket configuration
PocketConfig *PocketConfig `json:"pocketConfig,omitempty"`
// Todoist configuration
TodoistConfig *TodoistConfig `json:"todoistConfig,omitempty"`
// GitHub configuration
GitHubConfig *GitHubConfig `json:"gitHubConfig,omitempty"`
// Twitter configuration
TwitterConfig *TwitterConfig `json:"twitterConfig,omitempty"`
// Reddit configuration
RedditConfig *RedditConfig `json:"redditConfig,omitempty"`
// Obsidian configuration
ObsidianConfig *ObsidianConfig `json:"obsidianConfig,omitempty"`
}
// SlackConfig holds Slack-specific configuration
type SlackConfig struct {
TeamID string `json:"teamId"`
TeamName string `json:"teamName"`
ChannelID string `json:"channelId"`
ChannelName string `json:"channelName"`
BotUserID string `json:"botUserId"`
Scopes []string `json:"scopes"`
// Notification settings
NotifyTasks bool `json:"notifyTasks"`
NotifyBookmarks bool `json:"notifyBookmarks"`
NotifyNotes bool `json:"notifyNotes"`
NotifyDeadlines bool `json:"notifyDeadlines"`
NotifyTimeEntries bool `json:"notifyTimeEntries"`
}
// DiscordConfig holds Discord-specific configuration
type DiscordConfig struct {
GuildID string `json:"guildId"`
GuildName string `json:"guildName"`
ChannelID string `json:"channelId"`
ChannelName string `json:"channelName"`
BotUserID string `json:"botUserId"`
Scopes []string `json:"scopes"`
// Notification settings
NotifyTasks bool `json:"notifyTasks"`
NotifyBookmarks bool `json:"notifyBookmarks"`
NotifyNotes bool `json:"notifyNotes"`
NotifyDeadlines bool `json:"notifyDeadlines"`
NotifyTimeEntries bool `json:"notifyTimeEntries"`
}
// NotionConfig holds Notion-specific configuration
type NotionConfig struct {
DatabaseID string `json:"databaseId"`
WorkspaceID string `json:"workspaceId"`
WorkspaceName string `json:"workspaceName"`
// Sync settings
SyncBookmarks bool `json:"syncBookmarks"`
SyncTasks bool `json:"syncTasks"`
SyncNotes bool `json:"syncNotes"`
SyncFiles bool `json:"syncFiles"`
// Mapping settings
BookmarkDatabaseID string `json:"bookmarkDatabaseId"`
TaskDatabaseID string `json:"taskDatabaseId"`
NoteDatabaseID string `json:"noteDatabaseId"`
FileDatabaseID string `json:"fileDatabaseId"`
}
// GoogleConfig holds Google-specific configuration
type GoogleConfig struct {
// Google Drive
DriveEnabled bool `json:"driveEnabled"`
DriveFolderID string `json:"driveFolderId"`
// Google Calendar
CalendarEnabled bool `json:"calendarEnabled"`
CalendarIDs []string `json:"calendarIds"`
// Google Docs
DocsEnabled bool `json:"docsEnabled"`
// Sync settings
SyncBookmarks bool `json:"syncBookmarks"`
SyncTasks bool `json:"syncTasks"`
SyncNotes bool `json:"syncNotes"`
SyncFiles bool `json:"syncFiles"`
SyncCalendar bool `json:"syncCalendar"`
}
// PocketConfig holds Pocket-specific configuration
type PocketConfig struct {
Username string `json:"username"`
// Sync settings
SyncBookmarks bool `json:"syncBookmarks"`
SyncTags bool `json:"syncTags"`
ImportAll bool `json:"importAll"`
}
// TodoistConfig holds Todoist-specific configuration
type TodoistConfig struct {
ProjectID string `json:"projectId"`
ProjectName string `json:"projectName"`
// Sync settings
SyncTasks bool `json:"syncTasks"`
SyncProjects bool `json:"syncProjects"`
SyncLabels bool `json:"syncLabels"`
ImportAll bool `json:"importAll"`
}
// GitHubConfig holds GitHub-specific configuration
type GitHubConfig struct {
Username string `json:"username"`
RepoSync bool `json:"repoSync"`
IssueSync bool `json:"issueSync"`
PRSync bool `json:"prSync"`
StarSync bool `json:"starSync"`
WatchSync bool `json:"watchSync"`
}
// TwitterConfig holds Twitter-specific configuration
type TwitterConfig struct {
Username string `json:"username"`
SyncTweets bool `json:"syncTweets"`
SyncLikes bool `json:"syncLikes"`
SyncBookmarks bool `json:"syncBookmarks"`
}
// RedditConfig holds Reddit-specific configuration
type RedditConfig struct {
Username string `json:"username"`
SyncPosts bool `json:"syncPosts"`
SyncComments bool `json:"syncComments"`
SyncSaved bool `json:"syncSaved"`
SyncUpvoted bool `json:"syncUpvoted"`
}
// ObsidianConfig holds Obsidian-specific configuration
type ObsidianConfig struct {
VaultPath string `json:"vaultPath"`
VaultName string `json:"vaultName"`
SyncNotes bool `json:"syncNotes"`
SyncBookmarks bool `json:"syncBookmarks"`
SyncTasks bool `json:"syncTasks"`
AutoSync bool `json:"autoSync"`
}
// SyncLog represents a sync operation log
type SyncLog struct {
ID string `json:"id" gorm:"primaryKey;type:uuid;default:gen_random_uuid()"`
IntegrationID string `json:"integrationId" gorm:"not null;index;type:uuid"`
Type string `json:"type"` // "full", "incremental", "manual", "webhook"
Status string `json:"status"` // "success", "error", "partial"
// Sync statistics
ItemsProcessed int `json:"itemsProcessed"`
ItemsCreated int `json:"itemsCreated"`
ItemsUpdated int `json:"itemsUpdated"`
ItemsDeleted int `json:"itemsDeleted"`
ItemsSkipped int `json:"itemsSkipped"`
// Timing
StartedAt time.Time `json:"startedAt"`
CompletedAt *time.Time `json:"completedAt"`
Duration int `json:"duration"` // in seconds
// Error details
ErrorMessage string `json:"errorMessage" gorm:"type:text"`
ErrorDetails string `json:"errorDetails" gorm:"type:text"`
// Additional data
SyncData string `json:"syncData" gorm:"type:jsonb"`
// Timestamps
CreatedAt time.Time `json:"createdAt"`
// Relationships
Integration Integration `json:"integration,omitempty" gorm:"foreignKey:IntegrationID"`
}
// WebhookEvent represents an incoming webhook event
type WebhookEvent struct {
ID string `json:"id" gorm:"primaryKey;type:uuid;default:gen_random_uuid()"`
IntegrationID string `json:"integrationId" gorm:"not null;index;type:uuid"`
Type string `json:"type"` // "slack", "discord", etc.
EventType string `json:"eventType"` // "message", "reaction_added", etc.
// Event data
Payload string `json:"payload" gorm:"type:jsonb"`
Processed bool `json:"processed" gorm:"default:false"`
// Processing details
ProcessedAt *time.Time `json:"processedAt"`
ErrorMessage string `json:"errorMessage" gorm:"type:text"`
// Timestamps
CreatedAt time.Time `json:"createdAt"`
// Relationships
Integration Integration `json:"integration,omitempty" gorm:"foreignKey:IntegrationID"`
}
+246
View File
@@ -0,0 +1,246 @@
package models
import (
"regexp"
"strings"
"time"
"gorm.io/gorm"
)
// WikiPage represents a page in the knowledge base/wiki
type WikiPage struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Basic page information
Title string `json:"title" gorm:"not null"`
Slug string `json:"slug" gorm:"not null;uniqueIndex"`
Content string `json:"content" gorm:"type:text"`
Summary string `json:"summary" gorm:"type:text"`
Status string `json:"status" gorm:"default:draft"` // draft, published, archived
// Organization
CategoryID *uint `json:"category_id,omitempty"`
Category *Category `json:"category,omitempty" gorm:"foreignKey:CategoryID"`
ParentID *uint `json:"parent_id,omitempty"`
Parent *WikiPage `json:"parent,omitempty" gorm:"foreignKey:ParentID"`
Children []WikiPage `json:"children,omitempty" gorm:"foreignKey:ParentID"`
// Metadata
Tags []Tag `json:"tags,omitempty" gorm:"many2many:wiki_page_tags;"`
Keywords []string `json:"keywords" gorm:"serializer:json"`
ReadingTime int `json:"reading_time"` // estimated minutes
WordCount int `json:"word_count"`
ViewCount int `json:"view_count" gorm:"default:0"`
LastViewedAt *time.Time `json:"last_viewed_at,omitempty"`
IsPublic bool `json:"is_public" gorm:"default:false"`
IsTemplate bool `json:"is_template" gorm:"default:false"`
TemplateID *uint `json:"template_id,omitempty"`
Template *WikiPage `json:"template,omitempty" gorm:"foreignKey:TemplateID"`
// Collaboration
IsCollaborative bool `json:"is_collaborative" gorm:"default:false"`
Collaborators []User `json:"collaborators,omitempty" gorm:"many2many:wiki_collaborators;"`
LastEditedBy *uint `json:"last_edited_by,omitempty"`
LastEditedUser *User `json:"last_edited_user,omitempty" gorm:"foreignKey:LastEditedBy"`
EditCount int `json:"edit_count" gorm:"default:0"`
// Relationships
Versions []WikiVersion `json:"versions,omitempty" gorm:"foreignKey:WikiPageID"`
Backlinks []WikiBacklink `json:"backlinks,omitempty" gorm:"foreignKey:TargetPageID"`
Attachments []WikiAttachment `json:"attachments,omitempty" gorm:"foreignKey:WikiPageID"`
Bookmarks []Bookmark `json:"bookmarks,omitempty" gorm:"foreignKey:WikiPageID"`
Notes []Note `json:"notes,omitempty" gorm:"foreignKey:WikiPageID"`
}
// Category represents a category for organizing wiki pages
type Category struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Name string `json:"name" gorm:"not null"`
Slug string `json:"slug" gorm:"not null;uniqueIndex"`
Description string `json:"description"`
Color string `json:"color" gorm:"default:#6366f1"`
Icon string `json:"icon"`
ParentID *uint `json:"parent_id,omitempty"`
Parent *Category `json:"parent,omitempty" gorm:"foreignKey:ParentID"`
Children []Category `json:"children,omitempty" gorm:"foreignKey:ParentID"`
IsPublic bool `json:"is_public" gorm:"default:false"`
SortOrder int `json:"sort_order" gorm:"default:0"`
// Relationships
Pages []WikiPage `json:"pages,omitempty" gorm:"foreignKey:CategoryID"`
}
// WikiVersion represents a version history of a wiki page
type WikiVersion struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
WikiPageID uint `json:"wiki_page_id" gorm:"not null;index"`
WikiPage WikiPage `json:"wiki_page,omitempty" gorm:"foreignKey:WikiPageID"`
VersionNumber int `json:"version_number" gorm:"not null"`
Title string `json:"title" gorm:"not null"`
Content string `json:"content" gorm:"type:text"`
Summary string `json:"summary" gorm:"type:text"`
ChangeLog string `json:"change_log" gorm:"type:text"`
// Author information
AuthorID uint `json:"author_id" gorm:"not null"`
Author User `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
// Version metadata
WordCount int `json:"word_count"`
CharactersAdded int `json:"characters_added"`
CharactersRemoved int `json:"characters_removed"`
IsMinorChange bool `json:"is_minor_change" gorm:"default:false"`
}
// WikiBacklink represents a link between wiki pages
type WikiBacklink struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
SourcePageID uint `json:"source_page_id" gorm:"not null;index"`
SourcePage WikiPage `json:"source_page,omitempty" gorm:"foreignKey:SourcePageID"`
TargetPageID uint `json:"target_page_id" gorm:"not null;index"`
TargetPage WikiPage `json:"target_page,omitempty" gorm:"foreignKey:TargetPageID"`
LinkText string `json:"link_text"`
Context string `json:"context" gorm:"type:text"` // Surrounding text where the link appears
}
// WikiAttachment represents files attached to wiki pages
type WikiAttachment struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
WikiPageID uint `json:"wiki_page_id" gorm:"not null;index"`
WikiPage WikiPage `json:"wiki_page,omitempty" gorm:"foreignKey:WikiPageID"`
FileName string `json:"file_name" gorm:"not null"`
OriginalName string `json:"original_name" gorm:"not null"`
FilePath string `json:"file_path" gorm:"not null"`
FileSize int64 `json:"file_size"`
MimeType string `json:"mime_type"`
Width int `json:"width"` // For images
Height int `json:"height"` // For images
Thumbnail string `json:"thumbnail"`
Description string `json:"description"`
IsPublic bool `json:"is_public" gorm:"default:false"`
}
// Template represents reusable page templates
type Template struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Name string `json:"name" gorm:"not null"`
Slug string `json:"slug" gorm:"not null;uniqueIndex"`
Description string `json:"description"`
Content string `json:"content" gorm:"type:text"`
Category string `json:"category"` // meeting, project, documentation, etc.
IsPublic bool `json:"is_public" gorm:"default:false"`
UsageCount int `json:"usage_count" gorm:"default:0"`
// Template variables
Variables []TemplateVariable `json:"variables,omitempty" gorm:"foreignKey:TemplateID"`
}
// TemplateVariable represents variables in templates
type TemplateVariable struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
TemplateID uint `json:"template_id" gorm:"not null;index"`
Template Template `json:"template,omitempty" gorm:"foreignKey:TemplateID"`
Name string `json:"name" gorm:"not null"`
Type string `json:"type" gorm:"not null"` // text, number, date, select
DefaultValue string `json:"default_value"`
Required bool `json:"required" gorm:"default:false"`
Description string `json:"description"`
Options string `json:"options" gorm:"serializer:json"` // For select type
}
// BeforeCreate hooks
func (w *WikiPage) BeforeCreate(tx *gorm.DB) error {
if w.Status == "" {
w.Status = "draft"
}
if w.Slug == "" && w.Title != "" {
w.Slug = generateSlug(w.Title)
}
return nil
}
func (c *Category) BeforeCreate(tx *gorm.DB) error {
if c.Slug == "" && c.Name != "" {
c.Slug = generateSlug(c.Name)
}
return nil
}
func (t *Template) BeforeCreate(tx *gorm.DB) error {
if t.Slug == "" && t.Name != "" {
t.Slug = generateSlug(t.Name)
}
return nil
}
// BeforeUpdate hooks
func (w *WikiPage) BeforeUpdate(tx *gorm.DB) error {
if w.Title != "" {
w.Slug = generateSlug(w.Title)
}
if w.Content != "" {
w.WordCount = len(strings.Fields(w.Content))
w.ReadingTime = estimateReadingTime(w.WordCount)
}
return nil
}
// Helper functions
func generateSlug(title string) string {
// Simple slug generation - in production, you'd want more sophisticated handling
slug := strings.ToLower(title)
slug = strings.ReplaceAll(slug, " ", "-")
slug = regexp.MustCompile(`[^a-z0-9-]`).ReplaceAllString(slug, "")
slug = regexp.MustCompile(`-+`).ReplaceAllString(slug, "-")
slug = strings.Trim(slug, "-")
return slug
}
func estimateReadingTime(wordCount int) int {
readingSpeed := 225 // words per minute
readingTime := wordCount / readingSpeed
if readingTime < 1 {
readingTime = 1
}
return readingTime
}
+142
View File
@@ -0,0 +1,142 @@
package models
import (
"time"
"gorm.io/gorm"
)
// LearningPath represents a structured learning path
type LearningPath struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Basic information
Title string `json:"title" gorm:"not null"`
Description string `json:"description"`
Category string `json:"category" gorm:"not null"` // programming, design, business, etc.
Difficulty string `json:"difficulty" gorm:"default:beginner"` // beginner, intermediate, advanced
// Metadata
Duration string `json:"duration"` // estimated time to complete
Thumbnail string `json:"thumbnail"` // cover image
IsPublished bool `json:"is_published" gorm:"default:false"`
IsFeatured bool `json:"is_featured" gorm:"default:false"`
// Creator information
CreatorID uint `json:"creator_id" gorm:"not null;index"`
Creator User `json:"creator,omitempty" gorm:"foreignKey:CreatorID"`
// Relationships
Modules []LearningModule `json:"modules,omitempty" gorm:"foreignKey:LearningPathID"`
Courses []LearningPathCourse `json:"courses,omitempty" gorm:"foreignKey:LearningPathID"`
Tags []Tag `json:"tags,omitempty" gorm:"many2many:learning_path_tags;"`
Enrollments []Enrollment `json:"enrollments,omitempty" gorm:"foreignKey:LearningPathID"`
// Statistics
EnrollmentCount int `json:"enrollment_count" gorm:"default:0"`
Rating float64 `json:"rating" gorm:"default:0"`
ReviewCount int `json:"review_count" gorm:"default:0"`
}
// LearningModule represents a module within a learning path
type LearningModule struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Basic information
LearningPathID uint `json:"learning_path_id" gorm:"not null;index"`
LearningPath LearningPath `json:"learning_path,omitempty" gorm:"foreignKey:LearningPathID"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description"`
Content string `json:"content" gorm:"type:text"`
Order int `json:"order" gorm:"not null"`
// Module type
ModuleType string `json:"module_type" gorm:"default:lesson"` // lesson, project, quiz, video, reading
// Resources
Resources []ModuleResource `json:"resources,omitempty" gorm:"foreignKey:LearningModuleID"`
// Completion tracking
EstimatedDuration string `json:"estimated_duration"`
IsRequired bool `json:"is_required" gorm:"default:true"`
}
// ModuleResource represents a resource within a learning module
type ModuleResource struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
LearningModuleID uint `json:"learning_module_id" gorm:"not null;index"`
LearningModule LearningModule `json:"learning_module,omitempty" gorm:"foreignKey:LearningModuleID"`
Title string `json:"title" gorm:"not null"`
URL string `json:"url"`
Type string `json:"type" gorm:"not null"` // video, article, book, tool, download
Description string `json:"description"`
Order int `json:"order" gorm:"not null"`
// External resource metadata
Thumbnail string `json:"thumbnail"`
Duration string `json:"duration"`
IsExternal bool `json:"is_external" gorm:"default:true"`
}
// Enrollment represents a user's enrollment in a learning path
type Enrollment struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
LearningPathID uint `json:"learning_path_id" gorm:"not null;index"`
LearningPath LearningPath `json:"learning_path,omitempty" gorm:"foreignKey:LearningPathID"`
CourseID *uint `json:"course_id,omitempty"` // for direct course enrollment
Course *Course `json:"course,omitempty" gorm:"foreignKey:CourseID"`
// Enrollment status
Status string `json:"status" gorm:"default:enrolled"` // enrolled, in_progress, completed, dropped
StartedAt *time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at"`
// Progress tracking
Progress float64 `json:"progress" gorm:"default:0"` // percentage 0-100
CompletedModules []uint `json:"completed_modules" gorm:"serializer:json"`
CurrentModuleID *uint `json:"current_module_id"`
// User feedback
Rating *float64 `json:"rating"`
Review string `json:"review"`
ReviewDate *time.Time `json:"review_date"`
}
// Progress represents a user's progress in a specific module
type Progress struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
EnrollmentID uint `json:"enrollment_id" gorm:"not null;index"`
LearningModuleID uint `json:"learning_module_id" gorm:"not null;index"`
// Progress status
Status string `json:"status" gorm:"default:not_started"` // not_started, in_progress, completed
StartedAt *time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at"`
// Progress details
TimeSpent int `json:"time_spent"` // minutes
ProgressData string `json:"progress_data" gorm:"type:json"` // additional progress data
}
+230
View File
@@ -0,0 +1,230 @@
package models
import (
"time"
"gorm.io/gorm"
)
// MarketplaceItem represents an item in the knowledge marketplace
type MarketplaceItem struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Creator information
SellerID uint `json:"seller_id" gorm:"not null;index"`
Seller User `json:"seller,omitempty" gorm:"foreignKey:SellerID"`
// Basic information
Title string `json:"title" gorm:"not null"`
Description string `json:"description" gorm:"type:text"`
Category string `json:"category" gorm:"not null"` // course, template, tool, guide, resource
// Content type and reference
ContentType string `json:"content_type" gorm:"not null"` // bookmark_collection, note_template, course, learning_path, tool
ContentID *uint `json:"content_id,omitempty"` // Reference to actual content
ContentURL string `json:"content_url"` // Download/access URL
PreviewURL string `json:"preview_url"` // Preview/demo URL
Thumbnail string `json:"thumbnail"` // Item thumbnail
// Pricing
Price float64 `json:"price" gorm:"default:0"` // Price in USD
Currency string `json:"currency" gorm:"default:USD"` // Currency code
IsFree bool `json:"is_free" gorm:"default:false"` // Free item
Subscription bool `json:"subscription" gorm:"default:false"` // Subscription-based
SubscriptionPrice float64 `json:"subscription_price" gorm:"default:0"` // Monthly subscription price
// Ratings and reviews
Rating float64 `json:"rating" gorm:"default:0"` // Average rating (1-5)
ReviewCount int `json:"review_count" gorm:"default:0"` // Number of reviews
DownloadCount int `json:"download_count" gorm:"default:0"` // Number of downloads
// Status and visibility
Status string `json:"status" gorm:"default:draft"` // draft, published, suspended, removed
IsFeatured bool `json:"is_featured" gorm:"default:false"` // Featured item
IsApproved bool `json:"is_approved" gorm:"default:false"` // Admin approved
ApprovedAt *time.Time `json:"approved_at,omitempty"`
ApprovedBy *uint `json:"approved_by,omitempty"`
Approver *User `json:"approver,omitempty" gorm:"foreignKey:ApprovedBy"`
// Tags and metadata
Tags []MarketplaceTag `json:"tags,omitempty" gorm:"many2many:marketplace_item_tags;"`
License string `json:"license" gorm:"default:standard"` // License type
Version string `json:"version" gorm:"default:1.0"` // Version
LastUpdated *time.Time `json:"last_updated,omitempty"`
// Analytics
ViewCount int `json:"view_count" gorm:"default:0"`
LastViewedAt *time.Time `json:"last_viewed_at,omitempty"`
// Relationships
Reviews []MarketplaceReview `json:"reviews,omitempty" gorm:"foreignKey:ItemID"`
Purchases []MarketplacePurchase `json:"purchases,omitempty" gorm:"foreignKey:ItemID"`
}
// MarketplaceTag represents tags for marketplace items
type MarketplaceTag struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
Name string `json:"name" gorm:"uniqueIndex;not null"`
Description string `json:"description"`
Color string `json:"color" gorm:"default:#6366f1"` // Tag color
UsageCount int `json:"usage_count" gorm:"default:0"`
}
// MarketplaceReview represents a review for a marketplace item
type MarketplaceReview struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Review information
ItemID uint `json:"item_id" gorm:"not null;index"`
Item MarketplaceItem `json:"item,omitempty" gorm:"foreignKey:ItemID"`
ReviewerID uint `json:"reviewer_id" gorm:"not null;index"`
Reviewer User `json:"reviewer,omitempty" gorm:"foreignKey:ReviewerID"`
// Review content
Rating int `json:"rating" gorm:"not null;check:rating >= 1 AND rating <= 5"` // 1-5 stars
Title string `json:"title"`
Content string `json:"content" gorm:"type:text"`
// Review metadata
HelpfulCount int `json:"helpful_count" gorm:"default:0"`
IsVerified bool `json:"is_verified" gorm:"default:false"` // Verified purchase
PurchaseID *uint `json:"purchase_id,omitempty"`
ReviewedAt time.Time `json:"reviewed_at"`
// Status
Status string `json:"status" gorm:"default:published"` // published, hidden, removed
}
// MarketplacePurchase represents a purchase from the marketplace
type MarketplacePurchase struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Purchase information
ItemID uint `json:"item_id" gorm:"not null;index"`
Item MarketplaceItem `json:"item,omitempty" gorm:"foreignKey:ItemID"`
BuyerID uint `json:"buyer_id" gorm:"not null;index"`
Buyer User `json:"buyer,omitempty" gorm:"foreignKey:BuyerID"`
// Purchase details
Price float64 `json:"price" gorm:"not null"`
Currency string `json:"currency" gorm:"default:USD"`
PaymentMethod string `json:"payment_method"` // stripe, paypal, crypto
TransactionID string `json:"transaction_id" gorm:"uniqueIndex"`
// License and access
LicenseType string `json:"license_type" gorm:"default:personal"` // personal, commercial, enterprise
AccessGranted bool `json:"access_granted" gorm:"default:true"`
ExpiresAt *time.Time `json:"expires_at,omitempty"` // For subscriptions
// Status
Status string `json:"status" gorm:"default:completed"` // pending, completed, refunded, cancelled
RefundedAt *time.Time `json:"refunded_at,omitempty"`
RefundReason string `json:"refund_reason,omitempty"`
// Analytics
DownloadCount int `json:"download_count" gorm:"default:0"`
LastDownloadAt *time.Time `json:"last_download_at,omitempty"`
}
// ContentShare represents shared content links
type ContentShare struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Owner information
OwnerID uint `json:"owner_id" gorm:"not null;index"`
Owner User `json:"owner,omitempty" gorm:"foreignKey:OwnerID"`
// Content information
ContentType string `json:"content_type" gorm:"not null"` // bookmark, note, file, task, goal
ContentID uint `json:"content_id" gorm:"not null"`
// Share settings
ShareToken string `json:"share_token" gorm:"uniqueIndex;not null"`
ShareURL string `json:"share_url"`
Title string `json:"title"`
Description string `json:"description"`
Password string `json:"-" gorm:"column:password"` // Optional password protection
ExpiresAt *time.Time `json:"expires_at,omitempty"`
// Access control
AllowDownload bool `json:"allow_download" gorm:"default:true"`
AllowComment bool `json:"allow_comment" gorm:"default:false"`
AllowEdit bool `json:"allow_edit" gorm:"default:false"`
// Analytics
ViewCount int `json:"view_count" gorm:"default:0"`
DownloadCount int `json:"download_count" gorm:"default:0"`
LastAccessedAt *time.Time `json:"last_accessed_at,omitempty"`
// Status
IsActive bool `json:"is_active" gorm:"default:true"`
}
// BeforeCreate hooks
func (m *MarketplaceItem) BeforeCreate(tx *gorm.DB) error {
if m.Status == "" {
m.Status = "draft"
}
if m.Currency == "" {
m.Currency = "USD"
}
if m.Version == "" {
m.Version = "1.0"
}
if m.License == "" {
m.License = "standard"
}
return nil
}
func (r *MarketplaceReview) BeforeCreate(tx *gorm.DB) error {
if r.Status == "" {
r.Status = "published"
}
r.ReviewedAt = time.Now()
return nil
}
func (p *MarketplacePurchase) BeforeCreate(tx *gorm.DB) error {
if p.Status == "" {
p.Status = "completed"
}
if p.Currency == "" {
p.Currency = "USD"
}
if p.LicenseType == "" {
p.LicenseType = "personal"
}
return nil
}
func (s *ContentShare) BeforeCreate(tx *gorm.DB) error {
if s.ShareToken == "" {
// Generate a unique share token
s.ShareToken = generateShareToken()
}
return nil
}
// Helper function to generate share tokens
func generateShareToken() string {
// This should generate a cryptographically secure random token
// For now, using a simple implementation
return "share_" + time.Now().Format("20060102150405")
}
+88
View File
@@ -25,5 +25,93 @@ func AutoMigrate() {
&Task{},
&File{},
&Note{},
&TimeEntry{},
&FileAnalysis{},
&ChatSession{},
&ChatMessage{},
&LearningPath{},
&LearningModule{},
&ModuleResource{},
&Enrollment{},
&Progress{},
&Course{},
&LearningPathCourse{},
&CalendarEvent{},
&RecurrenceRule{},
&CalendarSettings{},
// Search models
&ContentEmbedding{},
&SavedSearch{},
&SavedSearchTag{},
&SearchAnalytics{},
&SearchSuggestion{},
// AI Feature models
&AISummary{},
&AITaskSuggestion{},
&UserAISettings{},
&AITagSuggestion{},
&AIContentGeneration{},
&AICodeReview{},
&AILearningRecommendation{},
// Advanced AI Recommendation models
&AIRecommendation{},
&UserPreference{},
&RecommendationInteraction{},
// Integration models
&Integration{},
&SyncLog{},
&WebhookEvent{},
// Analytics models
&Analytics{},
&ProductivityMetrics{},
&LearningAnalytics{},
&ContentAnalytics{},
&GitHubAnalytics{},
&HabitAnalytics{},
&Goal{},
&Milestone{},
&AnalyticsReport{},
// Social features models
&Skill{},
&Project{},
&ProjectTag{},
&SocialLink{},
&Follow{},
// Team workspace models
&Team{},
&TeamMember{},
&TeamInvitation{},
&TeamProject{},
&TeamProjectTag{},
&TeamBookmark{},
&TeamNote{},
&TeamTask{},
&TeamFile{},
&TeamActivity{},
// Security models
&AuditLog{},
// Marketplace models
&MarketplaceItem{},
&MarketplaceTag{},
&MarketplaceReview{},
&MarketplacePurchase{},
&ContentShare{},
// Community models
&Challenge{},
&ChallengeParticipant{},
&ChallengeTeam{},
&ChallengeMilestone{},
&ChallengeMilestoneCompletion{},
&ChallengeResource{},
&ChallengeTag{},
&Mentorship{},
&MentorshipSession{},
&MentorshipReview{},
&MentorshipMilestone{},
&MentorshipRequest{},
// YouTube cache models
&YouTubeChannelCache{},
// Video bookmark models
&VideoBookmark{},
)
}
+11 -7
View File
@@ -16,22 +16,26 @@ type Note struct {
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Title string `json:"title" gorm:"not null"`
Title string `json:"title" gorm:"not null"`
Content string `json:"content" gorm:"type:text"`
// Encryption
IsEncrypted bool `json:"is_encrypted" gorm:"default:false"`
EncryptionKey string `json:"-" gorm:"column:encryption_key"` // User-specific encryption key (optional)
// Organization
Tags []Tag `json:"tags,omitempty" gorm:"many2many:note_tags;"`
// Metadata
Description string `json:"description"`
IsPublic bool `json:"is_public" gorm:"default:false"`
IsPinned bool `json:"is_pinned" gorm:"default:false"`
// Formatting
ContentType string `json:"content_type" gorm:"default:markdown"` // markdown, html, plain
// Relationships
ParentNoteID *uint `json:"parent_note_id,omitempty"`
ParentNote *Note `json:"parent_note,omitempty" gorm:"foreignKey:ParentNoteID"`
ParentNoteID *uint `json:"parent_note_id,omitempty"`
ParentNote *Note `json:"parent_note,omitempty" gorm:"foreignKey:ParentNoteID"`
Subnotes []Note `json:"subnotes,omitempty" gorm:"foreignKey:ParentNoteID"`
}
+111
View File
@@ -0,0 +1,111 @@
package models
import (
"time"
"gorm.io/gorm"
)
// ContentEmbedding stores vector embeddings for semantic search
type ContentEmbedding struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Content reference
ContentType string `json:"content_type" gorm:"not null;index"` // 'bookmark', 'task', 'note', 'file'
ContentID uint `json:"content_id" gorm:"not null;index"`
// Embedding data
Embedding string `json:"embedding" gorm:"type:text"` // JSON array of floats
Model string `json:"model" gorm:"not null"` // AI model used
Dimensions int `json:"dimensions" gorm:"not null"` // Vector dimensions
TextContent string `json:"text_content" gorm:"type:text"` // Original text for embedding
// Metadata
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
// SavedSearch represents a user's saved search query
type SavedSearch struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Name string `json:"name" gorm:"not null"`
Query string `json:"query" gorm:"not null"`
Filters string `json:"filters" gorm:"type:json"` // JSON serialized filters
Alert bool `json:"alert" gorm:"default:false"`
LastRun *time.Time `json:"last_run"`
RunCount int `json:"run_count" gorm:"default:0"`
IsPublic bool `json:"is_public" gorm:"default:false"`
Description string `json:"description"`
Tags []SavedSearchTag `json:"tags,omitempty" gorm:"many2many:saved_search_tags;"`
}
// SavedSearchTag represents tags for saved searches
type SavedSearchTag struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `json:"name" gorm:"unique;not null"`
Color string `json:"color" gorm:"default:#3b82f6"`
}
// SearchAnalytics stores search analytics data
type SearchAnalytics struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Query string `json:"query" gorm:"not null;index"`
Filters string `json:"filters" gorm:"type:json"`
ResultsCount int `json:"results_count"`
Took int `json:"took"` // Time in milliseconds
ContentType string `json:"content_type"`
ClickedResultID *uint `json:"clicked_result_id"` // Track which result was clicked
SessionID string `json:"session_id" gorm:"index"`
IPAddress string `json:"ip_address"`
UserAgent string `json:"user_agent"`
}
// SearchSuggestion represents search suggestions
type SearchSuggestion struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
Text string `json:"text" gorm:"not null;uniqueIndex"`
Type string `json:"type" gorm:"not null"` // 'query', 'tag', 'content'
Frequency int `json:"frequency" gorm:"default:1"`
LastUsed time.Time `json:"last_used"`
ContentType *string `json:"content_type,omitempty"`
IsPublic bool `json:"is_public" gorm:"default:true"`
}
// BeforeCreate hook for ContentEmbedding
func (ce *ContentEmbedding) BeforeCreate(tx *gorm.DB) error {
// Set default model if not specified
if ce.Model == "" {
ce.Model = "text-embedding-ada-002"
}
// Set default dimensions if not specified
if ce.Dimensions == 0 {
ce.Dimensions = 1536 // Default for OpenAI embeddings
}
return nil
}
+96
View File
@@ -0,0 +1,96 @@
package models
import (
"time"
"gorm.io/gorm"
)
// Skill represents a user's skill
type Skill struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
Name string `json:"name" gorm:"not null"`
Level string `json:"level" gorm:"default:intermediate"` // beginner, intermediate, advanced, expert
Category string `json:"category"` // programming, design, business, etc.
Endorsements int `json:"endorsements" gorm:"default:0"`
Verified bool `json:"verified" gorm:"default:false"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
// Project represents a user's project showcase
type Project struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
Title string `json:"title" gorm:"not null"`
Description string `json:"description"`
RepositoryURL string `json:"repository_url"`
LiveURL string `json:"live_url"`
Thumbnail string `json:"thumbnail"`
Tags []ProjectTag `json:"tags,omitempty" gorm:"foreignKey:ProjectID"`
Featured bool `json:"featured" gorm:"default:false"`
Views int `json:"views" gorm:"default:0"`
Likes int `json:"likes" gorm:"default:0"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
// ProjectTag represents tags for projects
type ProjectTag struct {
ID uint `json:"id" gorm:"primaryKey"`
ProjectID uint `json:"project_id" gorm:"not null;index"`
Tag string `json:"tag" gorm:"not null"`
}
// SocialLink represents social media links
type SocialLink struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
Platform string `json:"platform" gorm:"not null"` // github, linkedin, twitter, etc.
URL string `json:"url" gorm:"not null"`
Username string `json:"username"`
Verified bool `json:"verified" gorm:"default:false"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
// Follow represents user following relationships
type Follow struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
FollowerID uint `json:"follower_id" gorm:"not null;index"`
FollowingID uint `json:"following_id" gorm:"not null;index"`
Follower User `json:"follower,omitempty" gorm:"foreignKey:FollowerID"`
Following User `json:"following,omitempty" gorm:"foreignKey:FollowingID"`
}
// UserProfileStats represents aggregated user statistics
type UserProfileStats struct {
UserID uint `json:"user_id"`
FollowersCount int `json:"followers_count"`
FollowingCount int `json:"following_count"`
PublicBookmarks int `json:"public_bookmarks"`
PublicNotes int `json:"public_notes"`
ProjectsCount int `json:"projects_count"`
SkillsCount int `json:"skills_count"`
TotalViews int `json:"total_views"`
TotalLikes int `json:"total_likes"`
ProfileCompletion float64 `json:"profile_completion"` // 0-100 percentage
}
+190
View File
@@ -0,0 +1,190 @@
package models
import (
"time"
"gorm.io/gorm"
)
// Team represents a collaborative workspace
type Team struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
Name string `json:"name" gorm:"not null"`
Description string `json:"description"`
Avatar string `json:"avatar"`
IsPublic bool `json:"is_public" gorm:"default:false"`
IsActive bool `json:"is_active" gorm:"default:true"`
// Owner of the team
OwnerID uint `json:"owner_id" gorm:"not null;index"`
Owner User `json:"owner,omitempty" gorm:"foreignKey:OwnerID"`
// Team members and relationships
Members []TeamMember `json:"members,omitempty" gorm:"foreignKey:TeamID"`
Invitations []TeamInvitation `json:"invitations,omitempty" gorm:"foreignKey:TeamID"`
Projects []TeamProject `json:"projects,omitempty" gorm:"foreignKey:TeamID"`
Bookmarks []TeamBookmark `json:"bookmarks,omitempty" gorm:"foreignKey:TeamID"`
Notes []TeamNote `json:"notes,omitempty" gorm:"foreignKey:TeamID"`
Tasks []TeamTask `json:"tasks,omitempty" gorm:"foreignKey:TeamID"`
Files []TeamFile `json:"files,omitempty" gorm:"foreignKey:TeamID"`
}
// TeamMember represents a user's membership in a team
type TeamMember struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
UserID uint `json:"user_id" gorm:"not null;index"`
Role string `json:"role" gorm:"default:member"` // owner, admin, member, viewer
JoinedAt time.Time `json:"joined_at"`
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
// TeamInvitation represents an invitation to join a team
type TeamInvitation struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
UserID uint `json:"user_id" gorm:"not null;index"`
Email string `json:"email" gorm:"not null"` // Email for non-registered users
Role string `json:"role" gorm:"default:member"`
Token string `json:"token" gorm:"uniqueIndex;not null"` // Invitation token
Status string `json:"status" gorm:"default:pending"` // pending, accepted, declined, expired
ExpiresAt time.Time `json:"expires_at"`
InvitedBy uint `json:"invited_by" gorm:"not null"`
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Inviter User `json:"inviter,omitempty" gorm:"foreignKey:InvitedBy"`
}
// TeamProject represents a project within a team
type TeamProject struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
Name string `json:"name" gorm:"not null"`
Description string `json:"description"`
Status string `json:"status" gorm:"default:active"` // active, archived, completed
RepositoryURL string `json:"repository_url"`
LiveURL string `json:"live_url"`
Tags []TeamProjectTag `json:"tags,omitempty" gorm:"foreignKey:ProjectID"`
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
}
// TeamProjectTag represents tags for team projects
type TeamProjectTag struct {
ID uint `json:"id" gorm:"primaryKey"`
ProjectID uint `json:"project_id" gorm:"not null;index"`
Tag string `json:"tag" gorm:"not null"`
}
// TeamBookmark represents a bookmark shared within a team
type TeamBookmark struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
UserID uint `json:"user_id" gorm:"not null;index"`
BookmarkID uint `json:"bookmark_id" gorm:"not null;index"`
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Bookmark Bookmark `json:"bookmark,omitempty" gorm:"foreignKey:BookmarkID"`
}
// TeamNote represents a note shared within a team
type TeamNote struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
UserID uint `json:"user_id" gorm:"not null;index"`
NoteID uint `json:"note_id" gorm:"not null;index"`
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Note Note `json:"note,omitempty" gorm:"foreignKey:NoteID"`
}
// TeamTask represents a task within a team
type TeamTask struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
UserID uint `json:"user_id" gorm:"not null;index"`
TaskID uint `json:"task_id" gorm:"not null;index"`
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Task Task `json:"task,omitempty" gorm:"foreignKey:TaskID"`
}
// TeamFile represents a file shared within a team
type TeamFile struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
UserID uint `json:"user_id" gorm:"not null;index"`
FileID uint `json:"file_id" gorm:"not null;index"`
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
File File `json:"file,omitempty" gorm:"foreignKey:FileID"`
}
// TeamActivity represents activity logs for team actions
type TeamActivity struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
TeamID uint `json:"team_id" gorm:"not null;index"`
UserID uint `json:"user_id" gorm:"not null;index"`
Action string `json:"action" gorm:"not null"` // created, updated, deleted, joined, left, etc.
EntityType string `json:"entity_type" gorm:"not null"` // team, project, bookmark, note, task, file
EntityID uint `json:"entity_id" gorm:"not null"`
Details string `json:"details"` // JSON string with additional details
Team Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
// TeamStats represents aggregated team statistics
type TeamStats struct {
TeamID uint `json:"team_id"`
MembersCount int64 `json:"members_count"`
ProjectsCount int64 `json:"projects_count"`
BookmarksCount int64 `json:"bookmarks_count"`
NotesCount int64 `json:"notes_count"`
TasksCount int64 `json:"tasks_count"`
FilesCount int64 `json:"files_count"`
RecentActivity int64 `json:"recent_activity"` // Activity in last 7 days
}
+102
View File
@@ -0,0 +1,102 @@
package models
import (
"fmt"
"time"
"gorm.io/gorm"
)
// TimeEntry represents a time tracking entry
type TimeEntry struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// What is being tracked
TaskID *uint `json:"task_id,omitempty"`
Task *Task `json:"task,omitempty" gorm:"foreignKey:TaskID"`
BookmarkID *uint `json:"bookmark_id,omitempty"`
Bookmark *Bookmark `json:"bookmark,omitempty" gorm:"foreignKey:BookmarkID"`
NoteID *uint `json:"note_id,omitempty"`
Note *Note `json:"note,omitempty" gorm:"foreignKey:NoteID"`
// Time tracking data
StartTime time.Time `json:"start_time" gorm:"not null"`
EndTime *time.Time `json:"end_time"`
Duration *int `json:"duration"` // Duration in seconds
Description string `json:"description"`
// Organization and metadata
Tags []Tag `json:"tags,omitempty" gorm:"many2many:time_entry_tags;"`
Billable bool `json:"billable" gorm:"default:false"`
// Billing information
HourlyRate *float64 `json:"hourly_rate"`
// Timer state
IsRunning bool `json:"is_running" gorm:"default:false"`
// Additional metadata
Source string `json:"source" gorm:"default:manual"` // manual, auto, pomodoro
}
// BeforeCreate hook to set default values
func (t *TimeEntry) BeforeCreate(tx *gorm.DB) error {
if t.StartTime.IsZero() {
t.StartTime = time.Now()
}
return nil
}
// BeforeUpdate hook to calculate duration when end time is set
func (t *TimeEntry) BeforeUpdate(tx *gorm.DB) error {
if t.EndTime != nil && !t.EndTime.IsZero() {
duration := int(t.EndTime.Sub(t.StartTime).Seconds())
t.Duration = &duration
t.IsRunning = false
}
return nil
}
// Stop stops the timer and calculates duration
func (t *TimeEntry) Stop() {
now := time.Now()
t.EndTime = &now
duration := int(now.Sub(t.StartTime).Seconds())
t.Duration = &duration
t.IsRunning = false
}
// GetDuration returns the duration in seconds
func (t *TimeEntry) GetDuration() int {
if t.Duration != nil {
return *t.Duration
}
if t.IsRunning {
return int(time.Since(t.StartTime).Seconds())
}
if t.EndTime != nil {
return int(t.EndTime.Sub(t.StartTime).Seconds())
}
return 0
}
// GetFormattedDuration returns a human-readable duration
func (t *TimeEntry) GetFormattedDuration() string {
duration := t.GetDuration()
hours := duration / 3600
minutes := (duration % 3600) / 60
seconds := duration % 60
if hours > 0 {
return fmt.Sprintf("%dh %dm %ds", hours, minutes, seconds)
} else if minutes > 0 {
return fmt.Sprintf("%dm %ds", minutes, seconds)
}
return fmt.Sprintf("%ds", seconds)
}
+46 -9
View File
@@ -17,15 +17,52 @@ type User struct {
Username string `json:"username" gorm:"uniqueIndex;not null"`
Password string `json:"-" gorm:"not null"` // Hashed password
FullName string `json:"full_name"`
Role string `json:"role" gorm:"default:user"` // user, admin
// GitHub OAuth fields
GitHubID int `json:"github_id" gorm:"uniqueIndex"`
AvatarURL string `json:"avatar_url"`
Provider string `json:"provider" gorm:"default:email"` // email, github
// Preferences
Theme string `json:"theme" gorm:"default:dark"`
Language string `json:"language" gorm:"default:en"`
Timezone string `json:"timezone" gorm:"default:UTC"`
Theme string `json:"theme" gorm:"default:dark"`
Language string `json:"language" gorm:"default:en"`
Timezone string `json:"timezone" gorm:"default:UTC"`
// Social Profile Features
Bio string `json:"bio"`
Location string `json:"location"`
Website string `json:"website"`
Company string `json:"company"`
JobTitle string `json:"job_title"`
Skills []Skill `json:"skills,omitempty" gorm:"foreignKey:UserID"`
Projects []Project `json:"projects,omitempty" gorm:"foreignKey:UserID"`
SocialLinks []SocialLink `json:"social_links,omitempty" gorm:"foreignKey:UserID"`
// Security & 2FA
TOTPSecret string `json:"-" gorm:"column:totp_secret"` // Encrypted TOTP secret
TOTPEnabled bool `json:"totp_enabled" gorm:"default:false"`
BackupCodes string `json:"-" gorm:"column:backup_codes"` // Encrypted backup codes
LastLoginAt *time.Time `json:"last_login_at"`
LoginAttempts int `json:"login_attempts" gorm:"default:0"`
LockedUntil *time.Time `json:"locked_until"`
// Privacy Settings
ProfileVisibility string `json:"profile_visibility" gorm:"default:public"` // public, private, friends
ShowEmail bool `json:"show_email" gorm:"default:false"`
ShowActivity bool `json:"show_activity" gorm:"default:true"`
AllowMessages bool `json:"allow_messages" gorm:"default:true"`
// Social Stats
FollowersCount int `json:"followers_count" gorm:"default:0"`
FollowingCount int `json:"following_count" gorm:"default:0"`
PublicBookmarks int `json:"public_bookmarks" gorm:"default:0"`
PublicNotes int `json:"public_notes" gorm:"default:0"`
// Relationships
Bookmarks []Bookmark `json:"bookmarks,omitempty" gorm:"foreignKey:UserID"`
Tasks []Task `json:"tasks,omitempty" gorm:"foreignKey:UserID"`
Files []File `json:"files,omitempty" gorm:"foreignKey:UserID"`
Notes []Note `json:"notes,omitempty" gorm:"foreignKey:UserID"`
Bookmarks []Bookmark `json:"bookmarks,omitempty" gorm:"foreignKey:UserID"`
Tasks []Task `json:"tasks,omitempty" gorm:"foreignKey:UserID"`
Files []File `json:"files,omitempty" gorm:"foreignKey:UserID"`
Notes []Note `json:"notes,omitempty" gorm:"foreignKey:UserID"`
TimeEntries []TimeEntry `json:"time_entries,omitempty" gorm:"foreignKey:UserID"`
}
+27
View File
@@ -0,0 +1,27 @@
package models
import (
"time"
)
// VideoBookmark represents a bookmarked YouTube video
type VideoBookmark struct {
ID uint `json:"id" gorm:"primaryKey"`
VideoID string `json:"video_id" gorm:"uniqueIndex;not null"` // YouTube video ID
Title string `json:"title" gorm:"not null"`
Channel string `json:"channel" gorm:"not null"`
Thumbnail string `json:"thumbnail" gorm:"not null"`
URL string `json:"url" gorm:"not null"`
UserID uint `json:"user_id" gorm:"not null"` // Foreign key to User
Description string `json:"description" gorm:"type:text"`
Tags string `json:"tags" gorm:"type:text"` // Comma-separated tags
IsWatched bool `json:"is_watched" gorm:"default:false"`
IsFavorite bool `json:"is_favorite" gorm:"default:false"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// TableName specifies the table name for VideoBookmark
func (VideoBookmark) TableName() string {
return "video_bookmarks"
}
+174
View File
@@ -0,0 +1,174 @@
package models
import (
"time"
"gorm.io/gorm"
)
// ScrapedContent represents content extracted from web pages
type ScrapedContent struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Source information
URL string `json:"url" gorm:"not null"`
Domain string `json:"domain"`
Title string `json:"title"`
Description string `json:"description"`
Author string `json:"author"`
PublishedDate *time.Time `json:"published_date"`
LastScraped time.Time `json:"last_scraped"`
// Extracted content
Content string `json:"content" gorm:"type:text"`
Summary string `json:"summary" gorm:"type:text"`
Keywords []string `json:"keywords" gorm:"serializer:json"`
Tags []Tag `json:"tags,omitempty" gorm:"many2many:scraped_content_tags;"`
Images []ScrapedImage `json:"images,omitempty" gorm:"foreignKey:ScrapedContentID"`
Links []ScrapedLink `json:"links,omitempty" gorm:"foreignKey:ScrapedContentID"`
Videos []ScrapedVideo `json:"videos,omitempty" gorm:"foreignKey:ScrapedContentID"`
// Content analysis
ContentType string `json:"content_type"` // article, blog, news, tutorial, documentation
WordCount int `json:"word_count"`
ReadingTime int `json:"reading_time"` // estimated minutes
Difficulty string `json:"difficulty"` // beginner, intermediate, advanced
QualityScore float64 `json:"quality_score"` // 0-100
// Processing status
Status string `json:"status" gorm:"default:pending"` // pending, processing, completed, failed
ErrorMessage string `json:"error_message"`
ProcessingLog string `json:"processing_log" gorm:"type:text"`
// Relationships
BookmarkID *uint `json:"bookmark_id,omitempty"`
Bookmark *Bookmark `json:"bookmark,omitempty" gorm:"foreignKey:BookmarkID"`
NoteID *uint `json:"note_id,omitempty"`
Note *Note `json:"note,omitempty" gorm:"foreignKey:NoteID"`
}
// ScrapedImage represents images extracted from web pages
type ScrapedImage struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
ScrapedContentID uint `json:"scraped_content_id" gorm:"not null;index"`
ScrapedContent ScrapedContent `json:"scraped_content,omitempty" gorm:"foreignKey:ScrapedContentID"`
URL string `json:"url"`
AltText string `json:"alt_text"`
Title string `json:"title"`
Width int `json:"width"`
Height int `json:"height"`
Format string `json:"format"` // jpg, png, gif, svg, webp
Size int64 `json:"size"` // bytes in bytes
IsMainImage bool `json:"is_main_image" gorm:"default:false"`
LocalPath string `json:"local_path"` // if downloaded
ThumbnailPath string `json:"thumbnail_path"` // if thumbnail generated
}
// ScrapedLink represents links extracted from web pages
type ScrapedLink struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
ScrapedContentID uint `json:"scraped_content_id" gorm:"not null;index"`
ScrapedContent ScrapedContent `json:"scraped_content,omitempty" gorm:"foreignKey:ScrapedContentID"`
URL string `json:"url"`
Text string `json:"text"`
Title string `json:"title"`
LinkType string `json:"link_type"` // internal, external, download, email
IsNoFollow bool `json:"is_no_follow"`
IsSponsored bool `json:"is_sponsored"`
Domain string `json:"domain"`
}
// ScrapedVideo represents videos extracted from web pages
type ScrapedVideo struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
ScrapedContentID uint `json:"scraped_content_id" gorm:"not null;index"`
ScrapedContent ScrapedContent `json:"scraped_content,omitempty" gorm:"foreignKey:ScrapedContentID"`
URL string `json:"url"`
Title string `json:"title"`
Description string `json:"description"`
Duration string `json:"duration"` // in format "HH:MM:SS"
Thumbnail string `json:"thumbnail"`
Platform string `json:"platform"` // youtube, vimeo, twitch, etc.
VideoID string `json:"video_id"` // platform-specific ID
IsEmbeddable bool `json:"is_embeddable"`
}
// ScrapingJob represents a web scraping job
type ScrapingJob struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
UserID uint `json:"user_id" gorm:"not null;index"`
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
// Job details
URL string `json:"url" gorm:"not null"`
JobType string `json:"job_type" gorm:"default:full_scrape"` // full_scrape, content_only, images_only, links_only
Priority string `json:"priority" gorm:"default:normal"` // low, normal, high, urgent
Status string `json:"status" gorm:"default:pending"` // pending, processing, completed, failed, cancelled
// Processing options
ExtractImages bool `json:"extract_images" gorm:"default:true"`
ExtractLinks bool `json:"extract_links" gorm:"default:true"`
ExtractVideos bool `json:"extract_videos" gorm:"default:true"`
GenerateSummary bool `json:"generate_summary" gorm:"default:true"`
DownloadImages bool `json:"download_images" gorm:"default:false"`
ExtractMetadata bool `json:"extract_metadata" gorm:"default:true"`
// Timing and results
StartedAt *time.Time `json:"started_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
Progress float64 `json:"progress" gorm:"default:0"` // 0-100
ErrorMessage string `json:"error_message"`
// Relationships
ScrapedContentID *uint `json:"scraped_content_id,omitempty"`
ScrapedContent *ScrapedContent `json:"scraped_content,omitempty" gorm:"foreignKey:ScrapedContentID"`
}
// BeforeCreate hooks
func (s *ScrapedContent) BeforeCreate(tx *gorm.DB) error {
if s.Status == "" {
s.Status = "pending"
}
if s.LastScraped.IsZero() {
s.LastScraped = time.Now()
}
return nil
}
func (j *ScrapingJob) BeforeCreate(tx *gorm.DB) error {
if j.Status == "" {
j.Status = "pending"
}
if j.Priority == "" {
j.Priority = "normal"
}
if j.JobType == "" {
j.JobType = "full_scrape"
}
return nil
}
+27
View File
@@ -0,0 +1,27 @@
package models
import (
"time"
)
// YouTubeChannelCache represents cached YouTube channel data
type YouTubeChannelCache struct {
ID int `json:"id" gorm:"primaryKey"`
ChannelID string `json:"channel_id" gorm:"uniqueIndex"`
ChannelName string `json:"channel_name"`
ChannelURL string `json:"channel_url"`
Videos string `json:"videos" gorm:"type:text"` // JSON array of videos
LastUpdated time.Time `json:"last_updated"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// TableName specifies the table name for YouTubeChannelCache
func (YouTubeChannelCache) TableName() string {
return "youtube_channel_cache"
}
// IsExpired checks if the cache is older than 2 hours
func (y *YouTubeChannelCache) IsExpired() bool {
return time.Since(y.LastUpdated) > 2*time.Hour
}