Scope knowledge and image libraries by brand
Frontend CI / Frontend (push) Successful in 2m59s
Backend CI / Backend (push) Successful in 14m58s

This commit is contained in:
2026-06-30 12:30:10 +08:00
parent 95ddb3057f
commit ced0c4ec0f
35 changed files with 1136 additions and 326 deletions
@@ -15,24 +15,31 @@ const countImageAssets = `-- name: CountImageAssets :one
SELECT COUNT(*)::INT AS total
FROM image_assets
WHERE tenant_id = $1
AND brand_id = $2
AND status = 'active'
AND deleted_at IS NULL
AND (
$2::BIGINT IS NULL
OR ($2::BIGINT = 0 AND folder_id IS NULL)
OR folder_id = $2::BIGINT
$3::BIGINT IS NULL
OR ($3::BIGINT = 0 AND folder_id IS NULL)
OR folder_id = $3::BIGINT
)
AND ($3::TEXT IS NULL OR name ILIKE '%' || $3::TEXT || '%')
AND ($4::TEXT IS NULL OR name ILIKE '%' || $4::TEXT || '%')
`
type CountImageAssetsParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
SearchQuery pgtype.Text `json:"search_query"`
}
func (q *Queries) CountImageAssets(ctx context.Context, arg CountImageAssetsParams) (int32, error) {
row := q.db.QueryRow(ctx, countImageAssets, arg.TenantID, arg.FolderID, arg.SearchQuery)
row := q.db.QueryRow(ctx, countImageAssets,
arg.TenantID,
arg.BrandID,
arg.FolderID,
arg.SearchQuery,
)
var total int32
err := row.Scan(&total)
return total, err
@@ -42,32 +49,42 @@ const countUncategorizedImages = `-- name: CountUncategorizedImages :one
SELECT COUNT(*)::INT AS count
FROM image_assets
WHERE tenant_id = $1
AND brand_id = $2
AND folder_id IS NULL
AND status = 'active'
AND deleted_at IS NULL
`
func (q *Queries) CountUncategorizedImages(ctx context.Context, tenantID int64) (int32, error) {
row := q.db.QueryRow(ctx, countUncategorizedImages, tenantID)
type CountUncategorizedImagesParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
func (q *Queries) CountUncategorizedImages(ctx context.Context, arg CountUncategorizedImagesParams) (int32, error) {
row := q.db.QueryRow(ctx, countUncategorizedImages, arg.TenantID, arg.BrandID)
var count int32
err := row.Scan(&count)
return count, err
}
const getImageAsset = `-- name: GetImageAsset :one
SELECT id, tenant_id, folder_id, object_key, name, size_bytes, status, created_by, created_at, updated_at
SELECT id, tenant_id, brand_id, folder_id, object_key, name, size_bytes, status, created_by, created_at, updated_at
FROM image_assets
WHERE id = $1 AND tenant_id = $2
WHERE id = $1
AND tenant_id = $2
AND brand_id = $3
`
type GetImageAssetParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
type GetImageAssetRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
ObjectKey string `json:"object_key"`
Name string `json:"name"`
@@ -79,11 +96,12 @@ type GetImageAssetRow struct {
}
func (q *Queries) GetImageAsset(ctx context.Context, arg GetImageAssetParams) (GetImageAssetRow, error) {
row := q.db.QueryRow(ctx, getImageAsset, arg.ID, arg.TenantID)
row := q.db.QueryRow(ctx, getImageAsset, arg.ID, arg.TenantID, arg.BrandID)
var i GetImageAssetRow
err := row.Scan(
&i.ID,
&i.TenantID,
&i.BrandID,
&i.FolderID,
&i.ObjectKey,
&i.Name,
@@ -97,13 +115,14 @@ func (q *Queries) GetImageAsset(ctx context.Context, arg GetImageAssetParams) (G
}
const insertImageAsset = `-- name: InsertImageAsset :one
INSERT INTO image_assets (tenant_id, folder_id, object_key, name, size_bytes, status, created_by)
VALUES ($1, $2, $3, $4, $5, $6, $7)
INSERT INTO image_assets (tenant_id, brand_id, folder_id, object_key, name, size_bytes, status, created_by)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id
`
type InsertImageAssetParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
ObjectKey string `json:"object_key"`
Name string `json:"name"`
@@ -115,6 +134,7 @@ type InsertImageAssetParams struct {
func (q *Queries) InsertImageAsset(ctx context.Context, arg InsertImageAssetParams) (int64, error) {
row := q.db.QueryRow(ctx, insertImageAsset,
arg.TenantID,
arg.BrandID,
arg.FolderID,
arg.ObjectKey,
arg.Name,
@@ -131,13 +151,15 @@ const listActiveImagesByFolder = `-- name: ListActiveImagesByFolder :many
SELECT id, object_key, size_bytes
FROM image_assets
WHERE tenant_id = $1
AND folder_id = $2
AND brand_id = $2
AND folder_id = $3
AND status = 'active'
AND deleted_at IS NULL
`
type ListActiveImagesByFolderParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
}
@@ -148,7 +170,7 @@ type ListActiveImagesByFolderRow struct {
}
func (q *Queries) ListActiveImagesByFolder(ctx context.Context, arg ListActiveImagesByFolderParams) ([]ListActiveImagesByFolderRow, error) {
rows, err := q.db.Query(ctx, listActiveImagesByFolder, arg.TenantID, arg.FolderID)
rows, err := q.db.Query(ctx, listActiveImagesByFolder, arg.TenantID, arg.BrandID, arg.FolderID)
if err != nil {
return nil, err
}
@@ -168,23 +190,25 @@ func (q *Queries) ListActiveImagesByFolder(ctx context.Context, arg ListActiveIm
}
const listImageAssets = `-- name: ListImageAssets :many
SELECT id, tenant_id, folder_id, object_key, name, size_bytes, status, created_by, created_at, updated_at
SELECT id, tenant_id, brand_id, folder_id, object_key, name, size_bytes, status, created_by, created_at, updated_at
FROM image_assets
WHERE tenant_id = $1
AND brand_id = $2
AND status = 'active'
AND deleted_at IS NULL
AND (
$2::BIGINT IS NULL
OR ($2::BIGINT = 0 AND folder_id IS NULL)
OR folder_id = $2::BIGINT
$3::BIGINT IS NULL
OR ($3::BIGINT = 0 AND folder_id IS NULL)
OR folder_id = $3::BIGINT
)
AND ($3::TEXT IS NULL OR name ILIKE '%' || $3::TEXT || '%')
AND ($4::TEXT IS NULL OR name ILIKE '%' || $4::TEXT || '%')
ORDER BY created_at DESC
LIMIT $5 OFFSET $4
LIMIT $6 OFFSET $5
`
type ListImageAssetsParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
SearchQuery pgtype.Text `json:"search_query"`
PageOffset int32 `json:"page_offset"`
@@ -194,6 +218,7 @@ type ListImageAssetsParams struct {
type ListImageAssetsRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
ObjectKey string `json:"object_key"`
Name string `json:"name"`
@@ -207,6 +232,7 @@ type ListImageAssetsRow struct {
func (q *Queries) ListImageAssets(ctx context.Context, arg ListImageAssetsParams) ([]ListImageAssetsRow, error) {
rows, err := q.db.Query(ctx, listImageAssets,
arg.TenantID,
arg.BrandID,
arg.FolderID,
arg.SearchQuery,
arg.PageOffset,
@@ -222,6 +248,7 @@ func (q *Queries) ListImageAssets(ctx context.Context, arg ListImageAssetsParams
if err := rows.Scan(
&i.ID,
&i.TenantID,
&i.BrandID,
&i.FolderID,
&i.ObjectKey,
&i.Name,
@@ -245,84 +272,113 @@ const markImagesInFolderPendingDelete = `-- name: MarkImagesInFolderPendingDelet
UPDATE image_assets
SET status = 'pending_delete', folder_id = NULL, updated_at = NOW()
WHERE tenant_id = $1
AND folder_id = $2
AND brand_id = $2
AND folder_id = $3
AND status = 'active'
AND deleted_at IS NULL
`
type MarkImagesInFolderPendingDeleteParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
}
func (q *Queries) MarkImagesInFolderPendingDelete(ctx context.Context, arg MarkImagesInFolderPendingDeleteParams) error {
_, err := q.db.Exec(ctx, markImagesInFolderPendingDelete, arg.TenantID, arg.FolderID)
_, err := q.db.Exec(ctx, markImagesInFolderPendingDelete, arg.TenantID, arg.BrandID, arg.FolderID)
return err
}
const updateImageAssetDeleted = `-- name: UpdateImageAssetDeleted :exec
UPDATE image_assets
SET status = 'deleted', deleted_at = NOW(), updated_at = NOW()
WHERE id = $1 AND tenant_id = $2
WHERE id = $1
AND tenant_id = $2
AND brand_id = $3
`
type UpdateImageAssetDeletedParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
func (q *Queries) UpdateImageAssetDeleted(ctx context.Context, arg UpdateImageAssetDeletedParams) error {
_, err := q.db.Exec(ctx, updateImageAssetDeleted, arg.ID, arg.TenantID)
_, err := q.db.Exec(ctx, updateImageAssetDeleted, arg.ID, arg.TenantID, arg.BrandID)
return err
}
const updateImageAssetFolder = `-- name: UpdateImageAssetFolder :exec
UPDATE image_assets
SET folder_id = $1, updated_at = NOW()
WHERE id = $2 AND tenant_id = $3
WHERE id = $2
AND tenant_id = $3
AND brand_id = $4
`
type UpdateImageAssetFolderParams struct {
FolderID pgtype.Int8 `json:"folder_id"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
func (q *Queries) UpdateImageAssetFolder(ctx context.Context, arg UpdateImageAssetFolderParams) error {
_, err := q.db.Exec(ctx, updateImageAssetFolder, arg.FolderID, arg.ID, arg.TenantID)
_, err := q.db.Exec(ctx, updateImageAssetFolder,
arg.FolderID,
arg.ID,
arg.TenantID,
arg.BrandID,
)
return err
}
const updateImageAssetName = `-- name: UpdateImageAssetName :exec
UPDATE image_assets
SET name = $1, updated_at = NOW()
WHERE id = $2 AND tenant_id = $3
WHERE id = $2
AND tenant_id = $3
AND brand_id = $4
`
type UpdateImageAssetNameParams struct {
Name string `json:"name"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
func (q *Queries) UpdateImageAssetName(ctx context.Context, arg UpdateImageAssetNameParams) error {
_, err := q.db.Exec(ctx, updateImageAssetName, arg.Name, arg.ID, arg.TenantID)
_, err := q.db.Exec(ctx, updateImageAssetName,
arg.Name,
arg.ID,
arg.TenantID,
arg.BrandID,
)
return err
}
const updateImageAssetStatus = `-- name: UpdateImageAssetStatus :exec
UPDATE image_assets
SET status = $1, updated_at = NOW()
WHERE id = $2 AND tenant_id = $3
WHERE id = $2
AND tenant_id = $3
AND brand_id = $4
`
type UpdateImageAssetStatusParams struct {
Status string `json:"status"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
func (q *Queries) UpdateImageAssetStatus(ctx context.Context, arg UpdateImageAssetStatusParams) error {
_, err := q.db.Exec(ctx, updateImageAssetStatus, arg.Status, arg.ID, arg.TenantID)
_, err := q.db.Exec(ctx, updateImageAssetStatus,
arg.Status,
arg.ID,
arg.TenantID,
arg.BrandID,
)
return err
}
@@ -15,36 +15,39 @@ const countActiveImagesInFolder = `-- name: CountActiveImagesInFolder :one
SELECT COUNT(*)::INT AS count
FROM image_assets
WHERE tenant_id = $1
AND folder_id = $2
AND brand_id = $2
AND folder_id = $3
AND status = 'active'
AND deleted_at IS NULL
`
type CountActiveImagesInFolderParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
FolderID pgtype.Int8 `json:"folder_id"`
}
func (q *Queries) CountActiveImagesInFolder(ctx context.Context, arg CountActiveImagesInFolderParams) (int32, error) {
row := q.db.QueryRow(ctx, countActiveImagesInFolder, arg.TenantID, arg.FolderID)
row := q.db.QueryRow(ctx, countActiveImagesInFolder, arg.TenantID, arg.BrandID, arg.FolderID)
var count int32
err := row.Scan(&count)
return count, err
}
const createImageFolder = `-- name: CreateImageFolder :one
INSERT INTO image_folders (tenant_id, name)
VALUES ($1, $2)
INSERT INTO image_folders (tenant_id, brand_id, name)
VALUES ($1, $2, $3)
RETURNING id
`
type CreateImageFolderParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
Name string `json:"name"`
}
func (q *Queries) CreateImageFolder(ctx context.Context, arg CreateImageFolderParams) (int64, error) {
row := q.db.QueryRow(ctx, createImageFolder, arg.TenantID, arg.Name)
row := q.db.QueryRow(ctx, createImageFolder, arg.TenantID, arg.BrandID, arg.Name)
var id int64
err := row.Scan(&id)
return id, err
@@ -52,44 +55,52 @@ func (q *Queries) CreateImageFolder(ctx context.Context, arg CreateImageFolderPa
const deleteImageFolder = `-- name: DeleteImageFolder :exec
DELETE FROM image_folders
WHERE id = $1 AND tenant_id = $2
WHERE id = $1
AND tenant_id = $2
AND brand_id = $3
`
type DeleteImageFolderParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
func (q *Queries) DeleteImageFolder(ctx context.Context, arg DeleteImageFolderParams) error {
_, err := q.db.Exec(ctx, deleteImageFolder, arg.ID, arg.TenantID)
_, err := q.db.Exec(ctx, deleteImageFolder, arg.ID, arg.TenantID, arg.BrandID)
return err
}
const getImageFolder = `-- name: GetImageFolder :one
SELECT id, tenant_id, name, created_at, updated_at
SELECT id, tenant_id, brand_id, name, created_at, updated_at
FROM image_folders
WHERE id = $1 AND tenant_id = $2
WHERE id = $1
AND tenant_id = $2
AND brand_id = $3
`
type GetImageFolderParams struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
type GetImageFolderRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
Name string `json:"name"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) GetImageFolder(ctx context.Context, arg GetImageFolderParams) (GetImageFolderRow, error) {
row := q.db.QueryRow(ctx, getImageFolder, arg.ID, arg.TenantID)
row := q.db.QueryRow(ctx, getImageFolder, arg.ID, arg.TenantID, arg.BrandID)
var i GetImageFolderRow
err := row.Scan(
&i.ID,
&i.TenantID,
&i.BrandID,
&i.Name,
&i.CreatedAt,
&i.UpdatedAt,
@@ -98,26 +109,33 @@ func (q *Queries) GetImageFolder(ctx context.Context, arg GetImageFolderParams)
}
const listImageFolders = `-- name: ListImageFolders :many
SELECT f.id, f.tenant_id, f.name, f.created_at, f.updated_at,
SELECT f.id, f.tenant_id, f.brand_id, f.name, f.created_at, f.updated_at,
COUNT(ia.id) FILTER (WHERE ia.status = 'active' AND ia.deleted_at IS NULL)::INT AS image_count
FROM image_folders f
LEFT JOIN image_assets ia ON ia.tenant_id = f.tenant_id AND ia.folder_id = f.id
LEFT JOIN image_assets ia ON ia.tenant_id = f.tenant_id AND ia.brand_id = f.brand_id AND ia.folder_id = f.id
WHERE f.tenant_id = $1
AND f.brand_id = $2
GROUP BY f.id
ORDER BY f.name
`
type ListImageFoldersParams struct {
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
type ListImageFoldersRow struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
Name string `json:"name"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ImageCount int32 `json:"image_count"`
}
func (q *Queries) ListImageFolders(ctx context.Context, tenantID int64) ([]ListImageFoldersRow, error) {
rows, err := q.db.Query(ctx, listImageFolders, tenantID)
func (q *Queries) ListImageFolders(ctx context.Context, arg ListImageFoldersParams) ([]ListImageFoldersRow, error) {
rows, err := q.db.Query(ctx, listImageFolders, arg.TenantID, arg.BrandID)
if err != nil {
return nil, err
}
@@ -128,6 +146,7 @@ func (q *Queries) ListImageFolders(ctx context.Context, tenantID int64) ([]ListI
if err := rows.Scan(
&i.ID,
&i.TenantID,
&i.BrandID,
&i.Name,
&i.CreatedAt,
&i.UpdatedAt,
@@ -146,16 +165,24 @@ func (q *Queries) ListImageFolders(ctx context.Context, tenantID int64) ([]ListI
const updateImageFolder = `-- name: UpdateImageFolder :exec
UPDATE image_folders
SET name = $1, updated_at = NOW()
WHERE id = $2 AND tenant_id = $3
WHERE id = $2
AND tenant_id = $3
AND brand_id = $4
`
type UpdateImageFolderParams struct {
Name string `json:"name"`
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
BrandID int64 `json:"brand_id"`
}
func (q *Queries) UpdateImageFolder(ctx context.Context, arg UpdateImageFolderParams) error {
_, err := q.db.Exec(ctx, updateImageFolder, arg.Name, arg.ID, arg.TenantID)
_, err := q.db.Exec(ctx, updateImageFolder,
arg.Name,
arg.ID,
arg.TenantID,
arg.BrandID,
)
return err
}
@@ -460,6 +460,7 @@ type ImageAsset struct {
CreatedAt pgtype.Timestamptz `json:"created_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
ContentHash pgtype.Text `json:"content_hash"`
BrandID int64 `json:"brand_id"`
}
type ImageAssetReference struct {
@@ -478,6 +479,7 @@ type ImageFolder struct {
Name string `json:"name"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
BrandID int64 `json:"brand_id"`
}
type KnowledgeChunksMetum struct {
@@ -517,6 +519,7 @@ type KnowledgeGroup struct {
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
BrandID int64 `json:"brand_id"`
}
type KnowledgeItem struct {
@@ -536,6 +539,7 @@ type KnowledgeItem struct {
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
MarkdownContent pgtype.Text `json:"markdown_content"`
BrandID int64 `json:"brand_id"`
}
type KnowledgeParseTask struct {
@@ -28,7 +28,7 @@ type Querier interface {
CountPromptRulesUngrouped(ctx context.Context, arg CountPromptRulesUngroupedParams) (int64, error)
CountPublishedArticlesByTenantAndBrand(ctx context.Context, arg CountPublishedArticlesByTenantAndBrandParams) (int64, error)
CountScheduleTasks(ctx context.Context, arg CountScheduleTasksParams) (int64, error)
CountUncategorizedImages(ctx context.Context, tenantID int64) (int32, error)
CountUncategorizedImages(ctx context.Context, arg CountUncategorizedImagesParams) (int32, error)
CreateArticle(ctx context.Context, arg CreateArticleParams) (int64, error)
CreateArticleVersion(ctx context.Context, arg CreateArticleVersionParams) (int64, error)
CreateAuditLog(ctx context.Context, arg CreateAuditLogParams) error
@@ -121,7 +121,7 @@ type Querier interface {
ListDesktopClientsByUser(ctx context.Context, arg ListDesktopClientsByUserParams) ([]DesktopClient, error)
ListDesktopClientsByWorkspace(ctx context.Context, workspaceID int64) ([]DesktopClient, error)
ListImageAssets(ctx context.Context, arg ListImageAssetsParams) ([]ListImageAssetsRow, error)
ListImageFolders(ctx context.Context, tenantID int64) ([]ListImageFoldersRow, error)
ListImageFolders(ctx context.Context, arg ListImageFoldersParams) ([]ListImageFoldersRow, error)
ListImageReferenceArticles(ctx context.Context, arg ListImageReferenceArticlesParams) ([]ListImageReferenceArticlesRow, error)
ListImageReferences(ctx context.Context, arg ListImageReferencesParams) ([]ListImageReferencesRow, error)
ListKeywords(ctx context.Context, arg ListKeywordsParams) ([]ListKeywordsRow, error)