This commit is contained in:
@@ -83,6 +83,10 @@ func main() {
|
||||
|
||||
hideList := make(map[string]bool)
|
||||
|
||||
if parts[1] != "story" {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Println("Loaded", parts[1], parts[2], "from archive.")
|
||||
|
||||
switch parts[1] {
|
||||
|
||||
@@ -108,7 +108,6 @@ func (r *characterRepository) Insert(ctx context.Context, character models.Chara
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
q := psqlcore.New(tx)
|
||||
|
||||
if !r.insertWithIDs || character.ID == "" {
|
||||
|
||||
@@ -77,7 +77,7 @@ func (d *DB) Posts() repositories.PostRepository {
|
||||
}
|
||||
|
||||
func (d *DB) Stories() repositories.StoryRepository {
|
||||
panic("implement me")
|
||||
return &storyRepository{insertWithIDs: d.insertWithIDs, db: d.db}
|
||||
}
|
||||
|
||||
func (d *DB) Chapters() repositories.ChapterRepository {
|
||||
|
||||
@@ -10,6 +10,53 @@ import (
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
const deleteStory = `-- name: DeleteStory :exec
|
||||
DELETE FROM story WHERE id=$1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteStory(ctx context.Context, id string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteStory, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const insertStory = `-- name: InsertStory :exec
|
||||
INSERT INTO story (id, author, name, category, open, listed, sort_by_fictional_date, created_date, fictional_date, updated_date)
|
||||
VALUES (
|
||||
$1::text, $2::text, $3::text, $4::text,
|
||||
$5::boolean, $6::boolean, $7::boolean,
|
||||
$8::timestamp, $9::timestamp, $10::timestamp
|
||||
)
|
||||
`
|
||||
|
||||
type InsertStoryParams struct {
|
||||
ID string `json:"id"`
|
||||
Author string `json:"author"`
|
||||
Name string `json:"name"`
|
||||
Category string `json:"category"`
|
||||
Open bool `json:"open"`
|
||||
Listed bool `json:"listed"`
|
||||
SortByFictionalDate bool `json:"sort_by_fictional_date"`
|
||||
CreatedDate time.Time `json:"created_date"`
|
||||
FictionalDate time.Time `json:"fictional_date"`
|
||||
UpdatedDate time.Time `json:"updated_date"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertStory(ctx context.Context, arg InsertStoryParams) error {
|
||||
_, err := q.db.ExecContext(ctx, insertStory,
|
||||
arg.ID,
|
||||
arg.Author,
|
||||
arg.Name,
|
||||
arg.Category,
|
||||
arg.Open,
|
||||
arg.Listed,
|
||||
arg.SortByFictionalDate,
|
||||
arg.CreatedDate,
|
||||
arg.FictionalDate,
|
||||
arg.UpdatedDate,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const selectStories = `-- name: SelectStories :many
|
||||
SELECT id, author, name, category, open, listed, sort_by_fictional_date, created_date, fictional_date, updated_date FROM story
|
||||
WHERE ($1::bool = false OR id = ANY($2::text[]))
|
||||
@@ -111,3 +158,43 @@ func (q *Queries) SelectStory(ctx context.Context, id string) (Story, error) {
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateStory = `-- name: UpdateStory :exec
|
||||
UPDATE story
|
||||
SET name=$1,
|
||||
category=$2,
|
||||
author=$3,
|
||||
open=$4,
|
||||
listed=$5,
|
||||
fictional_date=$6,
|
||||
updated_date=$7,
|
||||
sort_by_fictional_date=$8
|
||||
WHERE id=$9
|
||||
`
|
||||
|
||||
type UpdateStoryParams struct {
|
||||
Name string `json:"name"`
|
||||
Category string `json:"category"`
|
||||
Author string `json:"author"`
|
||||
Open bool `json:"open"`
|
||||
Listed bool `json:"listed"`
|
||||
FictionalDate time.Time `json:"fictional_date"`
|
||||
UpdatedDate time.Time `json:"updated_date"`
|
||||
SortByFictionalDate bool `json:"sort_by_fictional_date"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateStory(ctx context.Context, arg UpdateStoryParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateStory,
|
||||
arg.Name,
|
||||
arg.Category,
|
||||
arg.Author,
|
||||
arg.Open,
|
||||
arg.Listed,
|
||||
arg.FictionalDate,
|
||||
arg.UpdatedDate,
|
||||
arg.SortByFictionalDate,
|
||||
arg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -43,8 +43,26 @@ func (q *Queries) ClearTagsByTarget(ctx context.Context, arg ClearTagsByTargetPa
|
||||
return err
|
||||
}
|
||||
|
||||
const clearTagsByTargetLike = `-- name: ClearTagsByTargetLike :exec
|
||||
DELETE FROM common_tag
|
||||
WHERE target_kind=$1::TEXT
|
||||
AND target_id=$2::TEXT
|
||||
AND tag LIKE $3::TEXT
|
||||
`
|
||||
|
||||
type ClearTagsByTargetLikeParams struct {
|
||||
TargetKind string `json:"target_kind"`
|
||||
TargetID string `json:"target_id"`
|
||||
TagLike string `json:"tag_like"`
|
||||
}
|
||||
|
||||
func (q *Queries) ClearTagsByTargetLike(ctx context.Context, arg ClearTagsByTargetLikeParams) error {
|
||||
_, err := q.db.ExecContext(ctx, clearTagsByTargetLike, arg.TargetKind, arg.TargetID, arg.TagLike)
|
||||
return err
|
||||
}
|
||||
|
||||
const selectDistinctTags = `-- name: SelectDistinctTags :many
|
||||
SELECT DISTINCT tag FROM common_tag
|
||||
SELECT DISTINCT tag FROM common_tag ORDER BY tag
|
||||
`
|
||||
|
||||
func (q *Queries) SelectDistinctTags(ctx context.Context) ([]string, error) {
|
||||
@@ -70,12 +88,12 @@ func (q *Queries) SelectDistinctTags(ctx context.Context) ([]string, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const selectDistinctTagsByKind = `-- name: SelectDistinctTagsByKind :many
|
||||
SELECT DISTINCT tag FROM common_tag WHERE tag LIKE '$1::text%'
|
||||
const selectDistinctTagsLike = `-- name: SelectDistinctTagsLike :many
|
||||
SELECT DISTINCT tag FROM common_tag WHERE tag LIKE $1::text ORDER BY tag
|
||||
`
|
||||
|
||||
func (q *Queries) SelectDistinctTagsByKind(ctx context.Context) ([]string, error) {
|
||||
rows, err := q.db.QueryContext(ctx, selectDistinctTagsByKind)
|
||||
func (q *Queries) SelectDistinctTagsLike(ctx context.Context, dollar_1 string) ([]string, error) {
|
||||
rows, err := q.db.QueryContext(ctx, selectDistinctTagsLike, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,7 +116,7 @@ func (q *Queries) SelectDistinctTagsByKind(ctx context.Context) ([]string, error
|
||||
}
|
||||
|
||||
const selectTagsByTag = `-- name: SelectTagsByTag :many
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE tag = $1::text
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE tag = $1::text ORDER BY tag
|
||||
`
|
||||
|
||||
func (q *Queries) SelectTagsByTag(ctx context.Context, tagName string) ([]CommonTag, error) {
|
||||
@@ -125,7 +143,7 @@ func (q *Queries) SelectTagsByTag(ctx context.Context, tagName string) ([]Common
|
||||
}
|
||||
|
||||
const selectTagsByTags = `-- name: SelectTagsByTags :many
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE tag = ANY($1::text[])
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE tag = ANY($1::text[]) ORDER BY tag
|
||||
`
|
||||
|
||||
func (q *Queries) SelectTagsByTags(ctx context.Context, tagNames []string) ([]CommonTag, error) {
|
||||
@@ -152,16 +170,16 @@ func (q *Queries) SelectTagsByTags(ctx context.Context, tagNames []string) ([]Co
|
||||
}
|
||||
|
||||
const selectTagsByTarget = `-- name: SelectTagsByTarget :many
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE target_kind = $1 AND target_id = $2::text
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE target_kind = $1 AND target_id = $2::text ORDER BY tag
|
||||
`
|
||||
|
||||
type SelectTagsByTargetParams struct {
|
||||
TargetKind string `json:"target_kind"`
|
||||
Column2 string `json:"column_2"`
|
||||
TargetID string `json:"target_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) SelectTagsByTarget(ctx context.Context, arg SelectTagsByTargetParams) ([]CommonTag, error) {
|
||||
rows, err := q.db.QueryContext(ctx, selectTagsByTarget, arg.TargetKind, arg.Column2)
|
||||
rows, err := q.db.QueryContext(ctx, selectTagsByTarget, arg.TargetKind, arg.TargetID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -184,16 +202,16 @@ func (q *Queries) SelectTagsByTarget(ctx context.Context, arg SelectTagsByTarget
|
||||
}
|
||||
|
||||
const selectTagsByTargets = `-- name: SelectTagsByTargets :many
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE target_kind = $1 AND target_id = ANY($2::text[])
|
||||
SELECT tag, target_kind, target_id FROM common_tag WHERE target_kind = $1 AND target_id = ANY($2::text[]) ORDER BY tag
|
||||
`
|
||||
|
||||
type SelectTagsByTargetsParams struct {
|
||||
TargetKind string `json:"target_kind"`
|
||||
Column2 []string `json:"column_2"`
|
||||
TargetIds []string `json:"target_ids"`
|
||||
}
|
||||
|
||||
func (q *Queries) SelectTagsByTargets(ctx context.Context, arg SelectTagsByTargetsParams) ([]CommonTag, error) {
|
||||
rows, err := q.db.QueryContext(ctx, selectTagsByTargets, arg.TargetKind, pq.Array(arg.Column2))
|
||||
rows, err := q.db.QueryContext(ctx, selectTagsByTargets, arg.TargetKind, pq.Array(arg.TargetIds))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -215,6 +233,38 @@ func (q *Queries) SelectTagsByTargets(ctx context.Context, arg SelectTagsByTarge
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const selectTargetsByTags = `-- name: SelectTargetsByTags :many
|
||||
SELECT DISTINCT(target_id) FROM common_tag WHERE tag = ANY($1::text[]) AND target_kind = $2::text ORDER BY tag
|
||||
`
|
||||
|
||||
type SelectTargetsByTagsParams struct {
|
||||
TagNames []string `json:"tag_names"`
|
||||
TargetKind string `json:"target_kind"`
|
||||
}
|
||||
|
||||
func (q *Queries) SelectTargetsByTags(ctx context.Context, arg SelectTargetsByTagsParams) ([]string, error) {
|
||||
rows, err := q.db.QueryContext(ctx, selectTargetsByTags, pq.Array(arg.TagNames), arg.TargetKind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []string{}
|
||||
for rows.Next() {
|
||||
var target_id string
|
||||
if err := rows.Scan(&target_id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, target_id)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const setTag = `-- name: SetTag :exec
|
||||
INSERT INTO common_tag (tag, target_kind, target_id)
|
||||
VALUES (
|
||||
@@ -233,3 +283,20 @@ func (q *Queries) SetTag(ctx context.Context, arg SetTagParams) error {
|
||||
_, err := q.db.ExecContext(ctx, setTag, arg.Tag, arg.TargetKind, arg.TargetID)
|
||||
return err
|
||||
}
|
||||
|
||||
const setTags = `-- name: SetTags :exec
|
||||
INSERT INTO common_tag (tag, target_kind, target_id)
|
||||
SELECT unnest($1::TEXT[]), $2::TEXT as target_kind, $3::TEXT as target_id
|
||||
ON CONFLICT DO NOTHING
|
||||
`
|
||||
|
||||
type SetTagsParams struct {
|
||||
Tags []string `json:"tags"`
|
||||
TargetKind string `json:"target_kind"`
|
||||
TargetID string `json:"target_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) SetTags(ctx context.Context, arg SetTagsParams) error {
|
||||
_, err := q.db.ExecContext(ctx, setTags, pq.Array(arg.Tags), arg.TargetKind, arg.TargetID)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ WHERE (sqlc.arg(filter_keys)::bool = false OR keys && (sqlc.arg(keys)::text[]))
|
||||
AND (sqlc.arg(filter_earliest_date)::bool = false OR date >= sqlc.arg(earliest_date)::timestamp)
|
||||
AND (sqlc.arg(filter_latest_date)::bool = false OR date <= sqlc.arg(latest_date)::timestamp)
|
||||
AND (sqlc.arg(filter_author)::bool = false OR author = sqlc.arg(author)::text)
|
||||
ORDER BY date DESC
|
||||
LIMIT sqlc.arg(limit_size)::int;
|
||||
|
||||
-- name: InsertChange :exec
|
||||
|
||||
@@ -15,6 +15,7 @@ WHERE (sqlc.arg(filter_name)::bool = false OR name = ANY(sqlc.arg(names)::text[]
|
||||
AND (sqlc.arg(filter_logged)::bool = false OR logged = sqlc.arg(logged))
|
||||
AND (sqlc.arg(filter_event_name)::bool = false OR event_name = sqlc.arg(event_name))
|
||||
AND (sqlc.arg(filter_location_name)::bool = false OR location_name = sqlc.arg(location_name))
|
||||
ORDER BY name
|
||||
LIMIT sqlc.arg(limit_size)::int;
|
||||
|
||||
-- name: UpdateChannel :exec
|
||||
|
||||
@@ -10,4 +10,28 @@ WHERE (sqlc.arg(filter_id)::bool = false OR id = ANY(sqlc.arg(ids)::text[]))
|
||||
AND (sqlc.arg(filter_category)::bool = false OR category = sqlc.arg(category)::text)
|
||||
AND (sqlc.arg(filter_open)::bool = false OR open = sqlc.arg(open)::bool)
|
||||
AND (sqlc.arg(filter_unlisted)::bool = false OR unlisted = sqlc.arg(unlisted)::bool)
|
||||
ORDER BY updated_date
|
||||
LIMIT sqlc.arg(limit_size)::int;
|
||||
|
||||
-- name: InsertStory :exec
|
||||
INSERT INTO story (id, author, name, category, open, listed, sort_by_fictional_date, created_date, fictional_date, updated_date)
|
||||
VALUES (
|
||||
sqlc.arg(id)::text, sqlc.arg(author)::text, sqlc.arg(name)::text, sqlc.arg(category)::text,
|
||||
sqlc.arg(open)::boolean, sqlc.arg(listed)::boolean, sqlc.arg(sort_by_fictional_date)::boolean,
|
||||
sqlc.arg(created_date)::timestamp, sqlc.arg(fictional_date)::timestamp, sqlc.arg(updated_date)::timestamp
|
||||
);
|
||||
|
||||
-- name: UpdateStory :exec
|
||||
UPDATE story
|
||||
SET name=sqlc.arg(name),
|
||||
category=sqlc.arg(category),
|
||||
author=sqlc.arg(author),
|
||||
open=sqlc.arg(open),
|
||||
listed=sqlc.arg(listed),
|
||||
fictional_date=sqlc.arg(fictional_date),
|
||||
updated_date=sqlc.arg(updated_date),
|
||||
sort_by_fictional_date=sqlc.arg(sort_by_fictional_date)
|
||||
WHERE id=sqlc.arg(id);
|
||||
|
||||
-- name: DeleteStory :exec
|
||||
DELETE FROM story WHERE id=$1;
|
||||
@@ -5,31 +5,45 @@ VALUES (
|
||||
)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- name: SetTags :exec
|
||||
INSERT INTO common_tag (tag, target_kind, target_id)
|
||||
SELECT unnest(sqlc.arg(tags)::TEXT[]), sqlc.arg(target_kind)::TEXT as target_kind, sqlc.arg(target_id)::TEXT as target_id
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- name: ClearTag :exec
|
||||
DELETE FROM common_tag
|
||||
WHERE tag=sqlc.arg(tag)::TEXT
|
||||
AND target_kind=sqlc.arg(target_kind)::TEXT
|
||||
AND target_id=sqlc.arg(target_id)::TEXT;
|
||||
|
||||
-- name: ClearTagsByTargetLike :exec
|
||||
DELETE FROM common_tag
|
||||
WHERE target_kind=sqlc.arg(target_kind)::TEXT
|
||||
AND target_id=sqlc.arg(target_id)::TEXT
|
||||
AND tag LIKE sqlc.arg(tag_like)::TEXT;
|
||||
|
||||
-- name: ClearTagsByTarget :exec
|
||||
DELETE FROM common_tag
|
||||
WHERE target_kind=sqlc.arg(target_kind)::TEXT
|
||||
AND target_id=sqlc.arg(target_id)::TEXT;
|
||||
|
||||
-- name: SelectDistinctTags :many
|
||||
SELECT DISTINCT tag FROM common_tag;
|
||||
SELECT DISTINCT tag FROM common_tag ORDER BY tag;
|
||||
|
||||
-- name: SelectDistinctTagsByKind :many
|
||||
SELECT DISTINCT tag FROM common_tag WHERE tag LIKE '$1::text%';
|
||||
-- name: SelectDistinctTagsLike :many
|
||||
SELECT DISTINCT tag FROM common_tag WHERE tag LIKE $1::text ORDER BY tag;
|
||||
|
||||
-- name: SelectTagsByTag :many
|
||||
SELECT * FROM common_tag WHERE tag = sqlc.arg(tag_name)::text;
|
||||
SELECT * FROM common_tag WHERE tag = sqlc.arg(tag_name)::text ORDER BY tag;
|
||||
|
||||
-- name: SelectTagsByTags :many
|
||||
SELECT * FROM common_tag WHERE tag = ANY(sqlc.arg(tag_names)::text[]);
|
||||
SELECT * FROM common_tag WHERE tag = ANY(sqlc.arg(tag_names)::text[]) ORDER BY tag;
|
||||
|
||||
-- name: SelectTargetsByTags :many
|
||||
SELECT DISTINCT(target_id) FROM common_tag WHERE tag = ANY(sqlc.arg(tag_names)::text[]) AND target_kind = sqlc.arg(target_kind)::text ORDER BY tag;
|
||||
|
||||
-- name: SelectTagsByTarget :many
|
||||
SELECT * FROM common_tag WHERE target_kind = $1 AND target_id = $2::text;
|
||||
SELECT * FROM common_tag WHERE target_kind = sqlc.arg(target_kind) AND target_id = sqlc.arg(target_id)::text ORDER BY tag;
|
||||
|
||||
-- name: SelectTagsByTargets :many
|
||||
SELECT * FROM common_tag WHERE target_kind = $1 AND target_id = ANY($2::text[]);
|
||||
SELECT * FROM common_tag WHERE target_kind = sqlc.arg(target_kind) AND target_id = ANY(sqlc.arg(target_ids)::text[]) ORDER BY tag;
|
||||
|
||||
+129
-28
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"git.aiterp.net/rpdata/api/database/postgres/psqlcore"
|
||||
"git.aiterp.net/rpdata/api/internal/generate"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
@@ -35,72 +36,172 @@ func (r *storyRepository) List(ctx context.Context, filter models.StoryFilter) (
|
||||
params := psqlcore.SelectStoriesParams{LimitSize: 100}
|
||||
|
||||
if len(filter.Tags) > 0 {
|
||||
params.FilterID = true
|
||||
if len(filter.Tags) == 1 {
|
||||
tags, err := q.SelectTagsByKindName(ctx, psqlcore.SelectTagsByKindNameParams{
|
||||
Kind: string(filter.Tags[0].Kind),
|
||||
Name: filter.Tags[0].Name,
|
||||
targets, err := q.SelectTargetsByTags(ctx, psqlcore.SelectTargetsByTagsParams{
|
||||
TagNames: models.EncodeTagArray(filter.Tags),
|
||||
TargetKind: "Story",
|
||||
})
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
params.Ids = append(params.Ids, tag.TargetID)
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if len(params.Ids) == 0 {
|
||||
return []*models.Story{}, nil
|
||||
}
|
||||
|
||||
params.FilterID = true
|
||||
params.Ids = targets
|
||||
}
|
||||
if filter.Limit > 0 {
|
||||
params.LimitSize = 1000000
|
||||
if filter.Author != nil {
|
||||
params.FilterAuthor = true
|
||||
params.Author = *filter.Author
|
||||
}
|
||||
if filter.Category != nil {
|
||||
params.FilterCategory = true
|
||||
params.Category = string(*filter.Category)
|
||||
}
|
||||
if !filter.EarliestFictionalDate.IsZero() {
|
||||
params.FilterEarlistFictionalDate = true
|
||||
params.EarliestFictionalDate = filter.EarliestFictionalDate.UTC()
|
||||
}
|
||||
if !filter.LatestFictionalDate.IsZero() {
|
||||
params.FilterLastestFictionalDate = true
|
||||
params.LatestFictionalDate = filter.LatestFictionalDate.UTC()
|
||||
}
|
||||
if filter.Open != nil {
|
||||
params.FilterOpen = true
|
||||
params.Open = *filter.Open
|
||||
}
|
||||
if filter.Unlisted != nil {
|
||||
params.FilterUnlisted = true
|
||||
params.Unlisted = *filter.Unlisted
|
||||
}
|
||||
if filter.Limit <= 0 {
|
||||
params.LimitSize = 1000
|
||||
}
|
||||
|
||||
panic("implement me")
|
||||
stories, err := q.SelectStories(ctx, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
targetIDs := make([]string, len(stories))
|
||||
for i, story := range stories {
|
||||
targetIDs[i] = story.ID
|
||||
}
|
||||
tags, err := q.SelectTagsByTargets(ctx, psqlcore.SelectTagsByTargetsParams{
|
||||
TargetKind: "Story",
|
||||
TargetIds: targetIDs,
|
||||
})
|
||||
|
||||
return r.stories(stories, tags), nil
|
||||
}
|
||||
|
||||
func (r *storyRepository) Insert(ctx context.Context, story models.Story) (*models.Story, error) {
|
||||
panic("implement me")
|
||||
tx, err := r.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
q := psqlcore.New(tx)
|
||||
|
||||
if !r.insertWithIDs || len(story.ID) < 8 {
|
||||
story.ID = generate.StoryID()
|
||||
}
|
||||
|
||||
if story.UpdatedDate.Before(story.CreatedDate) {
|
||||
story.UpdatedDate = story.CreatedDate
|
||||
}
|
||||
|
||||
err = q.InsertStory(ctx, psqlcore.InsertStoryParams{
|
||||
ID: story.ID,
|
||||
Author: story.Author,
|
||||
Name: story.Name,
|
||||
Category: string(story.Category),
|
||||
Open: story.Open,
|
||||
Listed: story.Listed,
|
||||
SortByFictionalDate: story.SortByFictionalDate,
|
||||
CreatedDate: story.CreatedDate.UTC(),
|
||||
FictionalDate: story.FictionalDate.UTC(),
|
||||
UpdatedDate: story.UpdatedDate.UTC(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This is inefficient, but tags are very rarely added before the story is submitted.
|
||||
err = q.SetTags(ctx, psqlcore.SetTagsParams{
|
||||
Tags: models.EncodeTagArray(story.Tags),
|
||||
TargetKind: "Story",
|
||||
TargetID: story.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &story, tx.Commit()
|
||||
}
|
||||
|
||||
func (r *storyRepository) Update(ctx context.Context, story models.Story, update models.StoryUpdate) (*models.Story, error) {
|
||||
panic("implement me")
|
||||
story.ApplyUpdate(update)
|
||||
|
||||
err := psqlcore.New(r.db).UpdateStory(ctx, psqlcore.UpdateStoryParams{
|
||||
Name: story.Name,
|
||||
Category: string(story.Category),
|
||||
Author: story.Author,
|
||||
Open: story.Open,
|
||||
Listed: story.Listed,
|
||||
FictionalDate: story.FictionalDate.UTC(),
|
||||
UpdatedDate: story.UpdatedDate.UTC(),
|
||||
SortByFictionalDate: story.SortByFictionalDate,
|
||||
ID: story.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &story, nil
|
||||
}
|
||||
|
||||
func (r *storyRepository) AddTag(ctx context.Context, story models.Story, tag models.Tag) error {
|
||||
return psqlcore.New(r.db).SetTag(ctx, psqlcore.SetTagParams{
|
||||
Kind: string(tag.Kind),
|
||||
Name: tag.Name,
|
||||
TargetKind: "Story",
|
||||
TargetID: story.ID,
|
||||
Tag: tag.String(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r *storyRepository) RemoveTag(ctx context.Context, story models.Story, tag models.Tag) error {
|
||||
return psqlcore.New(r.db).ClearTag(ctx, psqlcore.ClearTagParams{
|
||||
Kind: string(tag.Kind),
|
||||
Name: tag.Name,
|
||||
TargetKind: "Story",
|
||||
TargetID: story.ID,
|
||||
Tag: tag.String(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r *storyRepository) Delete(ctx context.Context, story models.Story) error {
|
||||
panic("implement me")
|
||||
q := psqlcore.New(r.db)
|
||||
|
||||
err := q.ClearTagsByTarget(ctx, psqlcore.ClearTagsByTargetParams{
|
||||
TargetKind: "Story",
|
||||
TargetID: story.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.DeleteStory(ctx, story.ID)
|
||||
}
|
||||
|
||||
func (r *storyRepository) story(story psqlcore.Story, tags []psqlcore.CommonTag) *models.Story {
|
||||
tags2 := make([]models.Tag, 0, 8)
|
||||
storyTags := make([]models.Tag, 0, 8)
|
||||
for _, tag := range tags {
|
||||
if tag.TargetKind == "Story" && tag.TargetID == story.ID {
|
||||
tags2 = append(tags2, models.Tag{
|
||||
Kind: models.TagKind(tag.Kind),
|
||||
Name: tag.Name,
|
||||
})
|
||||
newTag := models.Tag{}
|
||||
err := newTag.Decode(tag.Tag)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
storyTags = append(storyTags, newTag)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +212,7 @@ func (r *storyRepository) story(story psqlcore.Story, tags []psqlcore.CommonTag)
|
||||
Category: models.StoryCategory(story.Category),
|
||||
Open: story.Open,
|
||||
Listed: story.Listed,
|
||||
Tags: tags2,
|
||||
Tags: storyTags,
|
||||
CreatedDate: story.CreatedDate,
|
||||
FictionalDate: story.FictionalDate,
|
||||
UpdatedDate: story.UpdatedDate,
|
||||
|
||||
@@ -13,19 +13,25 @@ type tagRepository struct {
|
||||
}
|
||||
|
||||
func (r *tagRepository) Find(ctx context.Context, kind models.TagKind, name string) (*models.Tag, error) {
|
||||
tag, err := psqlcore.New(r.db).SelectTagsByTag(ctx, fmt.Sprintf("%s:%s", kind, nmae))
|
||||
tag, err := psqlcore.New(r.db).SelectTagsByTag(ctx, fmt.Sprintf("%s:%s", kind, name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.Tag{Kind: models.TagKind(tag.Kind), Name: tag.Name}, nil
|
||||
tag2 := &models.Tag{}
|
||||
err = tag2.Decode(tag[0].Tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tag2, nil
|
||||
}
|
||||
|
||||
func (r *tagRepository) List(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error) {
|
||||
var tags []string
|
||||
var err error
|
||||
if filter.Kind != nil {
|
||||
tags, err = psqlcore.New(r.db).SelectDistinctTagsByKind(ctx, string(*filter.Kind))
|
||||
tags, err = psqlcore.New(r.db).SelectDistinctTagsLike(ctx, string(*filter.Kind)+"%")
|
||||
} else {
|
||||
tags, err = psqlcore.New(r.db).SelectDistinctTags(ctx)
|
||||
}
|
||||
@@ -36,11 +42,15 @@ func (r *tagRepository) List(ctx context.Context, filter models.TagFilter) ([]*m
|
||||
return models.DecodeTagArray(tags)
|
||||
}
|
||||
|
||||
func modelsTagsFromDataTags(tags []psqlcore.CommonTag) []*models.Tag {
|
||||
func modelsTagsFromDataTags(tags []psqlcore.CommonTag) ([]*models.Tag, error) {
|
||||
results := make([]*models.Tag, len(tags))
|
||||
for i, tag := range tags {
|
||||
results[i] = &models.Tag{Kind: models.TagKind(tag.Kind), Name: tag.Name}
|
||||
results[i] = &models.Tag{}
|
||||
err := results[i].Decode(tag.Tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -201,7 +201,6 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
|
||||
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
)
|
||||
|
||||
func complexity() (cr graphcore.ComplexityRoot) {
|
||||
tinySubListComplexity := 2
|
||||
subListComplexity := 25
|
||||
bigSublistComplexity := 75
|
||||
hugeSublistComplexity := 100
|
||||
@@ -175,7 +176,7 @@ func complexity() (cr graphcore.ComplexityRoot) {
|
||||
return childComplexity + bigSublistComplexity
|
||||
}
|
||||
cr.Story.Tags = func(childComplexity int) int {
|
||||
return childComplexity + subListComplexity
|
||||
return childComplexity + tinySubListComplexity
|
||||
}
|
||||
|
||||
cr.Chapter.Comments = func(childComplexity int, limit *int) int {
|
||||
|
||||
+28
-1
@@ -18,9 +18,36 @@ type Story struct {
|
||||
SortByFictionalDate bool `bson:"sortByFictionalDate"`
|
||||
}
|
||||
|
||||
func (story *Story) ApplyUpdate(update StoryUpdate) {
|
||||
if update.Name != nil {
|
||||
story.Name = *update.Name
|
||||
}
|
||||
if update.Category != nil {
|
||||
story.Category = *update.Category
|
||||
}
|
||||
if update.Author != nil {
|
||||
story.Author = *update.Author
|
||||
}
|
||||
if update.Open != nil {
|
||||
story.Open = *update.Open
|
||||
}
|
||||
if update.Listed != nil {
|
||||
story.Listed = *update.Listed
|
||||
}
|
||||
if update.SortByFictionalDate != nil {
|
||||
story.SortByFictionalDate = *update.SortByFictionalDate
|
||||
}
|
||||
if update.FictionalDate != nil {
|
||||
story.FictionalDate = *update.FictionalDate
|
||||
}
|
||||
if update.UpdatedDate != nil {
|
||||
story.UpdatedDate = *update.UpdatedDate
|
||||
}
|
||||
}
|
||||
|
||||
// IsChangeObject is an interface implementation to identify it as a valid
|
||||
// ChangeObject in GQL.
|
||||
func (*Story) IsChangeObject() {
|
||||
func (_ *Story) IsChangeObject() {
|
||||
panic("this method is a dummy, and so is its caller")
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,13 @@ func (s *CharacterService) List(ctx context.Context, filter models.CharacterFilt
|
||||
}
|
||||
|
||||
sort.Slice(characters, func(i, j int) bool {
|
||||
if len(characters[i].ID) > len(characters[j].ID) {
|
||||
return true
|
||||
}
|
||||
if len(characters[i].ID) < len(characters[j].ID) {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.Compare(characters[i].ID, characters[j].ID) < 0
|
||||
})
|
||||
|
||||
|
||||
@@ -34,6 +34,20 @@ func (s *StoryService) FindComment(ctx context.Context, id string) (*models.Comm
|
||||
}
|
||||
|
||||
func (s *StoryService) ListStories(ctx context.Context, filter models.StoryFilter) ([]*models.Story, error) {
|
||||
if filter.Unlisted != nil && *filter.Unlisted {
|
||||
token := s.authService.TokenFromContext(ctx)
|
||||
if !token.Authenticated() {
|
||||
return nil, errors.New("you cannot view unlisted stories")
|
||||
}
|
||||
if !token.Permitted("story.unlisted") {
|
||||
if filter.Author == nil {
|
||||
filter.Author = &token.UserID
|
||||
} else if *filter.Author != token.UserID {
|
||||
return nil, errors.New("you cannot view your own unlisted stories")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s.stories.List(ctx, filter)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user