Restructure the monorepo into clear top-level directories: - backend/: Go module root (cmd, internal, pkg, configs, migrations, docs/swagger, scripts, tests, go.mod, Makefile, .air.toml) - deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd - docs/: project documentation + reports/ (moved from repo root) - AGENTS.md: new AI coding-agent guide at repo root Update all references to the new layout: - Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root) - docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile, env_file ../../.env, volume mounts ../../backend:/app - deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile - CI: working-directory: backend for go commands, file deploy/docker/Dockerfile, coverage path backend/coverage.out, health_check backend/scripts/ - backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../ - README: architecture tree, quickstart, config paths updated Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh, gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to preserve history. Build, vet, SQLite tests, and docker compose config verified.
121 lines
4.3 KiB
Go
121 lines
4.3 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// DashboardAppRepo provides data access for DashboardApp.
|
|
type DashboardAppRepo struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewDashboardAppRepo(db *gorm.DB) *DashboardAppRepo {
|
|
return &DashboardAppRepo{db: db}
|
|
}
|
|
|
|
func (r *DashboardAppRepo) Create(ctx context.Context, app *model.DashboardApp) error {
|
|
return r.db.WithContext(ctx).Create(app).Error
|
|
}
|
|
|
|
func (r *DashboardAppRepo) GetByID(ctx context.Context, id uint) (*model.DashboardApp, error) {
|
|
var app model.DashboardApp
|
|
if err := r.db.WithContext(ctx).First(&app, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &app, nil
|
|
}
|
|
|
|
func (r *DashboardAppRepo) GetByAccountAndID(ctx context.Context, accountID, id uint) (*model.DashboardApp, error) {
|
|
var app model.DashboardApp
|
|
if err := r.db.WithContext(ctx).Where("account_id = ? AND id = ?", accountID, id).First(&app).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &app, nil
|
|
}
|
|
|
|
func (r *DashboardAppRepo) Update(ctx context.Context, app *model.DashboardApp) error {
|
|
return r.db.WithContext(ctx).Save(app).Error
|
|
}
|
|
|
|
func (r *DashboardAppRepo) Delete(ctx context.Context, id uint) error {
|
|
return r.db.WithContext(ctx).Delete(&model.DashboardApp{}, id).Error
|
|
}
|
|
|
|
func (r *DashboardAppRepo) DeleteByAccountAndID(ctx context.Context, accountID, id uint) error {
|
|
return r.db.WithContext(ctx).Where("account_id = ? AND id = ?", accountID, id).Delete(&model.DashboardApp{}).Error
|
|
}
|
|
|
|
// FindAllByAccountID returns all dashboard apps for an account (no pagination).
|
|
// Chatwoot: Current.account.dashboard_apps — returns all without limit/offset
|
|
func (r *DashboardAppRepo) FindAllByAccountID(ctx context.Context, accountID uint) ([]model.DashboardApp, error) {
|
|
var apps []model.DashboardApp
|
|
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).Find(&apps).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return apps, nil
|
|
}
|
|
|
|
func (r *DashboardAppRepo) FindByAccountID(ctx context.Context, accountID uint, offset, limit int) ([]model.DashboardApp, int64, error) {
|
|
var apps []model.DashboardApp
|
|
var count int64
|
|
db := r.db.WithContext(ctx).Model(&model.DashboardApp{}).Where("account_id = ?", accountID)
|
|
db.Count(&count)
|
|
if err := db.Offset(offset).Limit(limit).Find(&apps).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return apps, count, nil
|
|
}
|
|
|
|
func (r *DashboardAppRepo) FindByUserID(ctx context.Context, userID uint, offset, limit int) ([]model.DashboardApp, int64, error) {
|
|
var apps []model.DashboardApp
|
|
var count int64
|
|
db := r.db.WithContext(ctx).Model(&model.DashboardApp{}).Where("user_id = ?", userID)
|
|
db.Count(&count)
|
|
if err := db.Offset(offset).Limit(limit).Find(&apps).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return apps, count, nil
|
|
}
|
|
|
|
// Search searches dashboard apps by title (keyword match) within an account.
|
|
// Returns matching apps and total count, with pagination support.
|
|
// SearchAll returns all matching dashboard apps (no pagination).
|
|
func (r *DashboardAppRepo) SearchAll(ctx context.Context, accountID uint, query string) ([]model.DashboardApp, error) {
|
|
var apps []model.DashboardApp
|
|
searchPattern := "%" + query + "%"
|
|
if err := r.db.WithContext(ctx).Where("account_id = ? AND title LIKE ?", accountID, searchPattern).
|
|
Order("created_at DESC").Find(&apps).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return apps, nil
|
|
}
|
|
|
|
func (r *DashboardAppRepo) Search(ctx context.Context, accountID uint, query string, offset, limit int) ([]model.DashboardApp, int64, error) {
|
|
var apps []model.DashboardApp
|
|
var count int64
|
|
searchPattern := "%" + query + "%"
|
|
db := r.db.WithContext(ctx).Model(&model.DashboardApp{}).
|
|
Where("account_id = ? AND title LIKE ?", accountID, searchPattern)
|
|
db.Count(&count)
|
|
if err := db.Offset(offset).Limit(limit).Order("created_at DESC").Find(&apps).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return apps, count, nil
|
|
}
|
|
|
|
// FindActiveByAccountID returns only active dashboard apps for an account.
|
|
// FindAllActiveByAccountID returns all active dashboard apps for an account (no pagination).
|
|
func (r *DashboardAppRepo) FindAllActiveByAccountID(ctx context.Context, accountID uint) ([]model.DashboardApp, error) {
|
|
var apps []model.DashboardApp
|
|
if err := r.db.WithContext(ctx).
|
|
Where("account_id = ? AND active = ? AND deleted_at IS NULL", accountID, true).
|
|
Order("created_at DESC").
|
|
Find(&apps).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return apps, nil
|
|
}
|