Add Support for Advance Labels ( LabelV2)
Add Support for Custom Migration to keep supporting two database( sqlite and postgres) Migration from Label to LabelV2
This commit is contained in:
commit
8c4f0aa5ac
12 changed files with 730 additions and 49 deletions
|
@ -15,6 +15,7 @@ import (
|
|||
chModel "donetick.com/core/internal/chore/model"
|
||||
chRepo "donetick.com/core/internal/chore/repo"
|
||||
cRepo "donetick.com/core/internal/circle/repo"
|
||||
lRepo "donetick.com/core/internal/label/repo"
|
||||
nRepo "donetick.com/core/internal/notifier/repo"
|
||||
nps "donetick.com/core/internal/notifier/service"
|
||||
telegram "donetick.com/core/internal/notifier/telegram"
|
||||
|
@ -31,6 +32,10 @@ type ThingTrigger struct {
|
|||
Condition string `json:"condition"`
|
||||
}
|
||||
|
||||
type LabelReq struct {
|
||||
LabelID int `json:"id" binding:"required"`
|
||||
}
|
||||
|
||||
type ChoreReq struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
FrequencyType chModel.FrequencyType `json:"frequencyType"`
|
||||
|
@ -46,6 +51,7 @@ type ChoreReq struct {
|
|||
Notification bool `json:"notification"`
|
||||
NotificationMetadata *chModel.NotificationMetadata `json:"notificationMetadata"`
|
||||
Labels []string `json:"labels"`
|
||||
LabelsV2 *[]LabelReq `json:"labelsV2"`
|
||||
ThingTrigger *ThingTrigger `json:"thingTrigger"`
|
||||
}
|
||||
type Handler struct {
|
||||
|
@ -55,10 +61,11 @@ type Handler struct {
|
|||
nPlanner *nps.NotificationPlanner
|
||||
nRepo *nRepo.NotificationRepository
|
||||
tRepo *tRepo.ThingRepository
|
||||
lRepo *lRepo.LabelRepository
|
||||
}
|
||||
|
||||
func NewHandler(cr *chRepo.ChoreRepository, circleRepo *cRepo.CircleRepository, nt *telegram.TelegramNotifier,
|
||||
np *nps.NotificationPlanner, nRepo *nRepo.NotificationRepository, tRepo *tRepo.ThingRepository) *Handler {
|
||||
np *nps.NotificationPlanner, nRepo *nRepo.NotificationRepository, tRepo *tRepo.ThingRepository, lRepo *lRepo.LabelRepository) *Handler {
|
||||
return &Handler{
|
||||
choreRepo: cr,
|
||||
circleRepo: circleRepo,
|
||||
|
@ -66,6 +73,7 @@ func NewHandler(cr *chRepo.ChoreRepository, circleRepo *cRepo.CircleRepository,
|
|||
nPlanner: np,
|
||||
nRepo: nRepo,
|
||||
tRepo: tRepo,
|
||||
lRepo: lRepo,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,6 +270,17 @@ func (h *Handler) createChore(c *gin.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
labelsV2 := make([]int, len(*choreReq.LabelsV2))
|
||||
for i, label := range *choreReq.LabelsV2 {
|
||||
labelsV2[i] = int(label.LabelID)
|
||||
}
|
||||
if err := h.lRepo.AssignLabelsToChore(c, createdChore.ID, currentUser.ID, currentUser.CircleID, labelsV2, []int{}); err != nil {
|
||||
c.JSON(500, gin.H{
|
||||
"error": "Error adding labels",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.choreRepo.UpdateChoreAssignees(c, choreAssignees); err != nil {
|
||||
c.JSON(500, gin.H{
|
||||
"error": "Error adding chore assignees",
|
||||
|
@ -440,6 +459,38 @@ func (h *Handler) editChore(c *gin.Context) {
|
|||
labels := strings.Join(escapedLabels, ",")
|
||||
stringLabels = &labels
|
||||
}
|
||||
|
||||
// Create a map to store the existing labels for quick lookup
|
||||
oldLabelsMap := make(map[int]struct{})
|
||||
for _, oldLabel := range *oldChore.LabelsV2 {
|
||||
oldLabelsMap[oldLabel.ID] = struct{}{}
|
||||
}
|
||||
newLabelMap := make(map[int]struct{})
|
||||
for _, newLabel := range *choreReq.LabelsV2 {
|
||||
newLabelMap[newLabel.LabelID] = struct{}{}
|
||||
}
|
||||
// check what labels need to be added and what labels need to be deleted:
|
||||
labelsV2ToAdd := make([]int, 0)
|
||||
labelsV2ToBeRemoved := make([]int, 0)
|
||||
|
||||
for _, label := range *choreReq.LabelsV2 {
|
||||
if _, ok := oldLabelsMap[label.LabelID]; !ok {
|
||||
labelsV2ToAdd = append(labelsV2ToAdd, label.LabelID)
|
||||
}
|
||||
}
|
||||
for _, oldLabel := range *oldChore.LabelsV2 {
|
||||
if _, ok := newLabelMap[oldLabel.ID]; !ok {
|
||||
labelsV2ToBeRemoved = append(labelsV2ToBeRemoved, oldLabel.ID)
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.lRepo.AssignLabelsToChore(c, choreReq.ID, currentUser.ID, currentUser.CircleID, labelsV2ToAdd, labelsV2ToBeRemoved); err != nil {
|
||||
c.JSON(500, gin.H{
|
||||
"error": "Error adding labels",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
updatedChore := &chModel.Chore{
|
||||
ID: choreReq.ID,
|
||||
Name: choreReq.Name,
|
||||
|
|
|
@ -37,6 +37,7 @@ type Chore struct {
|
|||
Notification bool `json:"notification" gorm:"column:notification"` // Whether the chore has notification
|
||||
NotificationMetadata *string `json:"notificationMetadata" gorm:"column:notification_meta"` // Additional notification information
|
||||
Labels *string `json:"labels" gorm:"column:labels"` // Labels for the chore
|
||||
LabelsV2 *[]Label `json:"labelsV2" gorm:"many2many:chore_labels"` // Labels for the chore
|
||||
CircleID int `json:"circleId" gorm:"column:circle_id;index"` // The circle this chore is in
|
||||
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at"` // When the chore was created
|
||||
UpdatedAt time.Time `json:"updatedAt" gorm:"column:updated_at"` // When the chore was last updated
|
||||
|
@ -83,16 +84,6 @@ type Tag struct {
|
|||
Name string `json:"name" gorm:"column:name;unique"`
|
||||
}
|
||||
|
||||
// type ChoreTag struct {
|
||||
// ChoreID int `json:"choreId" gorm:"primaryKey;autoIncrement:false"`
|
||||
// TagID int `json:"tagId" gorm:"primaryKey;autoIncrement:false"`
|
||||
// }
|
||||
|
||||
// type CircleTag struct {
|
||||
// CircleID int `json:"circleId" gorm:"primaryKey;autoIncrement:false"`
|
||||
// TagID int `json:"tagId" gorm:"primaryKey;autoIncrement:false"`
|
||||
// }
|
||||
|
||||
type ChoreDetail struct {
|
||||
ID int `json:"id" gorm:"column:id"`
|
||||
Name string `json:"name" gorm:"column:name"`
|
||||
|
@ -106,3 +97,18 @@ type ChoreDetail struct {
|
|||
Notes *string `json:"notes" gorm:"column:notes"`
|
||||
CreatedBy int `json:"createdBy" gorm:"column:created_by"`
|
||||
}
|
||||
|
||||
type Label struct {
|
||||
ID int `json:"id" gorm:"primary_key"`
|
||||
Name string `json:"name" gorm:"column:name"`
|
||||
Color string `json:"color" gorm:"column:color"`
|
||||
CircleID *int `json:"-" gorm:"column:circle_id"`
|
||||
CreatedBy int `json:"created_by" gorm:"column:created_by"`
|
||||
}
|
||||
|
||||
type ChoreLabels struct {
|
||||
ChoreID int `json:"choreId" gorm:"primaryKey;autoIncrement:false"`
|
||||
LabelID int `json:"labelId" gorm:"primaryKey;autoIncrement:false"`
|
||||
UserID int `json:"userId" gorm:"primaryKey;autoIncrement:false"`
|
||||
Label Label
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func (r *ChoreRepository) CreateChore(c context.Context, chore *chModel.Chore) (
|
|||
|
||||
func (r *ChoreRepository) GetChore(c context.Context, choreID int) (*chModel.Chore, error) {
|
||||
var chore chModel.Chore
|
||||
if err := r.db.Debug().WithContext(c).Model(&chModel.Chore{}).Preload("Assignees").Preload("ThingChore").First(&chore, choreID).Error; err != nil {
|
||||
if err := r.db.Debug().WithContext(c).Model(&chModel.Chore{}).Preload("Assignees").Preload("ThingChore").Preload("LabelsV2").First(&chore, choreID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chore, nil
|
||||
|
@ -44,7 +44,7 @@ func (r *ChoreRepository) GetChore(c context.Context, choreID int) (*chModel.Cho
|
|||
func (r *ChoreRepository) GetChores(c context.Context, circleID int, userID int) ([]*chModel.Chore, error) {
|
||||
var chores []*chModel.Chore
|
||||
// if err := r.db.WithContext(c).Preload("Assignees").Where("is_active = ?", true).Order("next_due_date asc").Find(&chores, "circle_id = ?", circleID).Error; err != nil {
|
||||
if err := r.db.WithContext(c).Preload("Assignees").Joins("left join chore_assignees on chores.id = chore_assignees.chore_id").Where("chores.circle_id = ? AND (chores.created_by = ? OR chore_assignees.user_id = ?)", circleID, userID, userID).Group("chores.id").Order("next_due_date asc").Find(&chores, "circle_id = ?", circleID).Error; err != nil {
|
||||
if err := r.db.WithContext(c).Preload("Assignees").Preload("LabelsV2").Joins("left join chore_assignees on chores.id = chore_assignees.chore_id").Where("chores.circle_id = ? AND (chores.created_by = ? OR chore_assignees.user_id = ?)", circleID, userID, userID).Group("chores.id").Order("next_due_date asc").Find(&chores, "circle_id = ?", circleID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return chores, nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue