322 lines
7.8 KiB
Go
322 lines
7.8 KiB
Go
package models
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"log"
|
|
"screenmark/screenmark/.gen/haystack/haystack/model"
|
|
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
|
|
|
. "github.com/go-jet/jet/v2/postgres"
|
|
"github.com/go-jet/jet/v2/qrm"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type UserModel struct {
|
|
dbPool *sql.DB
|
|
}
|
|
|
|
type ImageWithProperties struct {
|
|
ID uuid.UUID
|
|
|
|
Image model.Image
|
|
|
|
Locations []model.Locations
|
|
Events []model.Events
|
|
Notes []model.Notes
|
|
Contacts []model.Contacts
|
|
}
|
|
|
|
type PropertiesWithImage struct {
|
|
Locations []struct {
|
|
model.Locations
|
|
|
|
Images uuid.UUIDs
|
|
}
|
|
Contacts []struct {
|
|
model.Contacts
|
|
|
|
Images uuid.UUIDs
|
|
}
|
|
Events []struct {
|
|
model.Events
|
|
|
|
Images uuid.UUIDs
|
|
}
|
|
Notes []struct {
|
|
model.Notes
|
|
|
|
Images uuid.UUIDs
|
|
}
|
|
}
|
|
|
|
func transpose(imageProperties []ImageWithProperties) PropertiesWithImage {
|
|
// EntityID -> []ImageIDs
|
|
dependencies := make(map[uuid.UUID]uuid.UUIDs)
|
|
|
|
addDependency := func(entityId uuid.UUID, imageId uuid.UUID) {
|
|
deps, exists := dependencies[entityId]
|
|
if !exists {
|
|
dep := uuid.UUIDs{imageId}
|
|
dependencies[entityId] = dep
|
|
|
|
return
|
|
}
|
|
|
|
dependencies[entityId] = append(deps, imageId)
|
|
}
|
|
|
|
contactMap := make(map[uuid.UUID]model.Contacts)
|
|
locationMap := make(map[uuid.UUID]model.Locations)
|
|
noteMap := make(map[uuid.UUID]model.Notes)
|
|
eventMap := make(map[uuid.UUID]model.Events)
|
|
|
|
for _, image := range imageProperties {
|
|
for _, contact := range image.Contacts {
|
|
contactMap[contact.ID] = contact
|
|
addDependency(contact.ID, image.Image.ID)
|
|
}
|
|
for _, location := range image.Locations {
|
|
locationMap[location.ID] = location
|
|
addDependency(location.ID, image.Image.ID)
|
|
}
|
|
for _, note := range image.Notes {
|
|
noteMap[note.ID] = note
|
|
addDependency(note.ID, image.Image.ID)
|
|
}
|
|
for _, event := range image.Events {
|
|
eventMap[event.ID] = event
|
|
addDependency(event.ID, image.Image.ID)
|
|
}
|
|
}
|
|
|
|
properties := PropertiesWithImage{
|
|
Contacts: make([]struct {
|
|
model.Contacts
|
|
Images uuid.UUIDs
|
|
}, 0),
|
|
Locations: make([]struct {
|
|
model.Locations
|
|
Images uuid.UUIDs
|
|
}, 0),
|
|
Notes: make([]struct {
|
|
model.Notes
|
|
Images uuid.UUIDs
|
|
}, 0),
|
|
Events: make([]struct {
|
|
model.Events
|
|
Images uuid.UUIDs
|
|
}, 0),
|
|
}
|
|
|
|
for contactId, contact := range contactMap {
|
|
properties.Contacts = append(properties.Contacts, struct {
|
|
model.Contacts
|
|
Images uuid.UUIDs
|
|
}{
|
|
Contacts: contact,
|
|
Images: dependencies[contactId],
|
|
})
|
|
}
|
|
|
|
for locationId, location := range locationMap {
|
|
properties.Locations = append(properties.Locations, struct {
|
|
model.Locations
|
|
Images uuid.UUIDs
|
|
}{
|
|
Locations: location,
|
|
Images: dependencies[locationId],
|
|
})
|
|
}
|
|
|
|
for noteId, note := range noteMap {
|
|
properties.Notes = append(properties.Notes, struct {
|
|
model.Notes
|
|
Images uuid.UUIDs
|
|
}{
|
|
Notes: note,
|
|
Images: dependencies[noteId],
|
|
})
|
|
}
|
|
|
|
for eventId, event := range eventMap {
|
|
properties.Events = append(properties.Events, struct {
|
|
model.Events
|
|
Images uuid.UUIDs
|
|
}{
|
|
Events: event,
|
|
Images: dependencies[eventId],
|
|
})
|
|
}
|
|
|
|
return properties
|
|
}
|
|
|
|
type TypedProperties struct {
|
|
Type string `json:"type"`
|
|
Data any `json:"data"`
|
|
}
|
|
|
|
func propertiesToTypeArray(properties PropertiesWithImage) []TypedProperties {
|
|
typedProperties := make([]TypedProperties, 0)
|
|
|
|
for _, location := range properties.Locations {
|
|
typedProperties = append(typedProperties, TypedProperties{
|
|
Type: "location",
|
|
Data: location,
|
|
})
|
|
}
|
|
|
|
for _, contact := range properties.Contacts {
|
|
typedProperties = append(typedProperties, TypedProperties{
|
|
Type: "contact",
|
|
Data: contact,
|
|
})
|
|
}
|
|
|
|
for _, note := range properties.Notes {
|
|
typedProperties = append(typedProperties, TypedProperties{
|
|
Type: "note",
|
|
Data: note,
|
|
})
|
|
}
|
|
|
|
for _, event := range properties.Events {
|
|
typedProperties = append(typedProperties, TypedProperties{
|
|
Type: "event",
|
|
Data: event,
|
|
})
|
|
}
|
|
|
|
return typedProperties
|
|
}
|
|
|
|
func GetTypedImageProperties(imageProperties []ImageWithProperties) []TypedProperties {
|
|
return propertiesToTypeArray(transpose(imageProperties))
|
|
}
|
|
|
|
func getUserIdFromImage(ctx context.Context, dbPool *sql.DB, imageId uuid.UUID) (uuid.UUID, error) {
|
|
getUserIdStmt := UserImages.SELECT(UserImages.UserID).WHERE(UserImages.ImageID.EQ(UUID(imageId)))
|
|
|
|
log.Println(getUserIdStmt.DebugSql())
|
|
|
|
userImages := []model.UserImages{}
|
|
err := getUserIdStmt.QueryContext(ctx, dbPool, &userImages)
|
|
if err != nil {
|
|
return uuid.Nil, err
|
|
}
|
|
|
|
if len(userImages) != 1 {
|
|
return uuid.Nil, errors.New("Expected exactly one choice.")
|
|
}
|
|
|
|
return userImages[0].UserID, nil
|
|
}
|
|
|
|
func getListImagesStmt() SelectStatement {
|
|
return SELECT(
|
|
UserImages.ID.AS("ImageWithProperties.ID"),
|
|
Image.ID,
|
|
Image.ImageName,
|
|
ImageTags.AllColumns,
|
|
UserTags.AllColumns,
|
|
ImageText.AllColumns,
|
|
ImageLinks.AllColumns,
|
|
ImageLocations.AllColumns,
|
|
Locations.AllColumns,
|
|
ImageEvents.AllColumns,
|
|
Events.AllColumns,
|
|
ImageContacts.AllColumns,
|
|
Contacts.AllColumns,
|
|
ImageNotes.AllColumns,
|
|
Notes.AllColumns,
|
|
).
|
|
FROM(
|
|
UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID)).
|
|
LEFT_JOIN(ImageTags, ImageTags.ImageID.EQ(Image.ID)).
|
|
LEFT_JOIN(UserTags, UserTags.ID.EQ(ImageTags.TagID)).
|
|
LEFT_JOIN(ImageText, ImageText.ImageID.EQ(Image.ID)).
|
|
LEFT_JOIN(ImageLinks, ImageLinks.ImageID.EQ(Image.ID)).
|
|
LEFT_JOIN(ImageLocations, ImageLocations.ImageID.EQ(UserImages.ImageID)).
|
|
LEFT_JOIN(Locations, Locations.ID.EQ(ImageLocations.LocationID)).
|
|
LEFT_JOIN(ImageEvents, ImageEvents.ImageID.EQ(UserImages.ImageID)).
|
|
LEFT_JOIN(Events, Events.ID.EQ(ImageEvents.EventID)).
|
|
LEFT_JOIN(ImageContacts, ImageContacts.ImageID.EQ(UserImages.ImageID)).
|
|
LEFT_JOIN(Contacts, Contacts.ID.EQ(ImageContacts.ContactID)).
|
|
LEFT_JOIN(ImageNotes, ImageNotes.ImageID.EQ(UserImages.ImageID)).
|
|
LEFT_JOIN(Notes, Notes.ID.EQ(ImageNotes.NoteID)))
|
|
}
|
|
|
|
func (m UserModel) ListImageWithProperties(ctx context.Context, userId uuid.UUID, imageId uuid.UUID) (ImageWithProperties, error) {
|
|
listImagePropertiesStmt := getListImagesStmt().
|
|
WHERE(UserImages.ImageID.EQ(UUID(imageId)))
|
|
|
|
image := ImageWithProperties{}
|
|
err := listImagePropertiesStmt.QueryContext(ctx, m.dbPool, &image)
|
|
|
|
return image, err
|
|
}
|
|
|
|
func (m UserModel) ListWithProperties(ctx context.Context, userId uuid.UUID) ([]ImageWithProperties, error) {
|
|
listWithPropertiesStmt := getListImagesStmt().
|
|
WHERE(UserImages.UserID.EQ(UUID(userId)))
|
|
|
|
images := []ImageWithProperties{}
|
|
err := listWithPropertiesStmt.QueryContext(ctx, m.dbPool, &images)
|
|
|
|
return images, err
|
|
}
|
|
|
|
func (m UserModel) GetUserIdFromEmail(ctx context.Context, email string) (uuid.UUID, error) {
|
|
getUserIdStmt := Users.SELECT(Users.ID).WHERE(Users.Email.EQ(String(email)))
|
|
|
|
user := model.Users{}
|
|
err := getUserIdStmt.QueryContext(ctx, m.dbPool, &user)
|
|
|
|
return user.ID, err
|
|
}
|
|
|
|
func (m UserModel) DoesUserExist(ctx context.Context, email string) bool {
|
|
getUserIdStmt := Users.SELECT(Users.ID).WHERE(Users.Email.EQ(String(email)))
|
|
|
|
user := model.Users{}
|
|
err := getUserIdStmt.QueryContext(ctx, m.dbPool, &user)
|
|
|
|
return err != qrm.ErrNoRows
|
|
}
|
|
|
|
func (m UserModel) Save(ctx context.Context, user model.Users) (model.Users, error) {
|
|
insertUserStmt := Users.INSERT(Users.Email).VALUES(user.Email).RETURNING(Users.AllColumns)
|
|
|
|
insertedUser := model.Users{}
|
|
err := insertUserStmt.QueryContext(ctx, m.dbPool, &insertedUser)
|
|
|
|
return insertedUser, err
|
|
}
|
|
|
|
type UserImageWithImage struct {
|
|
model.UserImages
|
|
|
|
Image model.Image
|
|
}
|
|
|
|
func (m UserModel) GetUserImages(ctx context.Context, userId uuid.UUID) ([]UserImageWithImage, error) {
|
|
getUserImagesStmt := SELECT(
|
|
UserImages.AllColumns,
|
|
Image.ID,
|
|
Image.ImageName,
|
|
).
|
|
FROM(UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID))).
|
|
WHERE(UserImages.UserID.EQ(UUID(userId)))
|
|
|
|
userImages := []UserImageWithImage{}
|
|
err := getUserImagesStmt.QueryContext(ctx, m.dbPool, &userImages)
|
|
|
|
return userImages, err
|
|
}
|
|
|
|
func NewUserModel(db *sql.DB) UserModel {
|
|
return UserModel{dbPool: db}
|
|
}
|