aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorNathaniel Sabanski2023-02-11 00:12:41 -0800
committerGitHub2023-02-11 16:12:41 +0800
commitfb1a2a13f05665764a6f91ed1a421b9e93c4e8c9 (patch)
tree7b1501f82d484811bd5630f3fc9233f132ee0df4 /models
parente9288c24773157411edec17c9bbcc8c1567e91ee (diff)
Preview images for Issue cards in Project Board view (#22112)
Original Issue: https://github.com/go-gitea/gitea/issues/22102 This addition would be a big benefit for design and art teams using the issue tracking. The preview will be the latest "image type" attachments on an issue- simple, and allows for automatic updates of the cover image as issue progress is made! This would make Gitea competitive with Trello... wouldn't it be amazing to say goodbye to Atlassian products? Ha. First image is the most recent, the SQL will fetch up to 5 latest images (URL string). All images supported by browsers plus upcoming formats: *.avif *.bmp *.gif *.jpg *.jpeg *.jxl *.png *.svg *.webp The CSS will try to center-align images until it cannot, then it will left align with overflow hidden. Single images get to be slightly larger! Tested so far on: Chrome, Firefox, Android Chrome, Android Firefox. Current revision with light and dark themes: ![image](https://user-images.githubusercontent.com/24665/207066878-58e6bf73-0c93-4caa-8d40-38f4432b3578.png) ![image](https://user-images.githubusercontent.com/24665/207066555-293f65c3-e706-4888-8516-de8ec632d638.png) --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: delvh <dev.lh@web.de>
Diffstat (limited to 'models')
-rw-r--r--models/migrations/migrations.go2
-rw-r--r--models/migrations/v1_19/v241.go17
-rw-r--r--models/project/board.go21
-rw-r--r--models/project/project.go34
-rw-r--r--models/project/project_test.go1
-rw-r--r--models/repo/attachment.go15
6 files changed, 85 insertions, 5 deletions
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 15600f057..79e857388 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -455,6 +455,8 @@ var migrations = []Migration{
NewMigration("Add scope for access_token", v1_19.AddScopeForAccessTokens),
// v240 -> v241
NewMigration("Add actions tables", v1_19.AddActionsTables),
+ // v241 -> v242
+ NewMigration("Add card_type column to project table", v1_19.AddCardTypeToProjectTable),
}
// GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v1_19/v241.go b/models/migrations/v1_19/v241.go
new file mode 100644
index 000000000..332be580f
--- /dev/null
+++ b/models/migrations/v1_19/v241.go
@@ -0,0 +1,17 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_19 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+// AddCardTypeToProjectTable: add CardType column, setting existing rows to CardTypeTextOnly
+func AddCardTypeToProjectTable(x *xorm.Engine) error {
+ type Project struct {
+ CardType int `xorm:"NOT NULL"`
+ }
+
+ return x.Sync(new(Project))
+}
diff --git a/models/project/board.go b/models/project/board.go
index d8468f0cb..dc4e2e688 100644
--- a/models/project/board.go
+++ b/models/project/board.go
@@ -19,6 +19,9 @@ type (
// BoardType is used to represent a project board type
BoardType uint8
+ // CardType is used to represent a project board card type
+ CardType uint8
+
// BoardList is a list of all project boards in a repository
BoardList []*Board
)
@@ -34,6 +37,14 @@ const (
BoardTypeBugTriage
)
+const (
+ // CardTypeTextOnly is a project board card type that is text only
+ CardTypeTextOnly CardType = iota
+
+ // CardTypeImagesAndText is a project board card type that has images and text
+ CardTypeImagesAndText
+)
+
// BoardColorPattern is a regexp witch can validate BoardColor
var BoardColorPattern = regexp.MustCompile("^#[0-9a-fA-F]{6}$")
@@ -85,6 +96,16 @@ func IsBoardTypeValid(p BoardType) bool {
}
}
+// IsCardTypeValid checks if the project board card type is valid
+func IsCardTypeValid(p CardType) bool {
+ switch p {
+ case CardTypeTextOnly, CardTypeImagesAndText:
+ return true
+ default:
+ return false
+ }
+}
+
func createBoardsForProjectsType(ctx context.Context, project *Project) error {
var items []string
diff --git a/models/project/project.go b/models/project/project.go
index 9074fd0c1..931ef4467 100644
--- a/models/project/project.go
+++ b/models/project/project.go
@@ -19,12 +19,18 @@ import (
)
type (
- // ProjectsConfig is used to identify the type of board that is being created
- ProjectsConfig struct {
+ // BoardConfig is used to identify the type of board that is being created
+ BoardConfig struct {
BoardType BoardType
Translation string
}
+ // CardConfig is used to identify the type of board card that is being used
+ CardConfig struct {
+ CardType CardType
+ Translation string
+ }
+
// Type is used to identify the type of project in question and ownership
Type uint8
)
@@ -91,6 +97,7 @@ type Project struct {
CreatorID int64 `xorm:"NOT NULL"`
IsClosed bool `xorm:"INDEX"`
BoardType BoardType
+ CardType CardType
Type Type
RenderedContent string `xorm:"-"`
@@ -145,15 +152,23 @@ func init() {
db.RegisterModel(new(Project))
}
-// GetProjectsConfig retrieves the types of configurations projects could have
-func GetProjectsConfig() []ProjectsConfig {
- return []ProjectsConfig{
+// GetBoardConfig retrieves the types of configurations project boards could have
+func GetBoardConfig() []BoardConfig {
+ return []BoardConfig{
{BoardTypeNone, "repo.projects.type.none"},
{BoardTypeBasicKanban, "repo.projects.type.basic_kanban"},
{BoardTypeBugTriage, "repo.projects.type.bug_triage"},
}
}
+// GetCardConfig retrieves the types of configurations project board cards could have
+func GetCardConfig() []CardConfig {
+ return []CardConfig{
+ {CardTypeTextOnly, "repo.projects.card_type.text_only"},
+ {CardTypeImagesAndText, "repo.projects.card_type.images_and_text"},
+ }
+}
+
// IsTypeValid checks if a project type is valid
func IsTypeValid(p Type) bool {
switch p {
@@ -237,6 +252,10 @@ func NewProject(p *Project) error {
p.BoardType = BoardTypeNone
}
+ if !IsCardTypeValid(p.CardType) {
+ p.CardType = CardTypeTextOnly
+ }
+
if !IsTypeValid(p.Type) {
return util.NewInvalidArgumentErrorf("project type is not valid")
}
@@ -280,9 +299,14 @@ func GetProjectByID(ctx context.Context, id int64) (*Project, error) {
// UpdateProject updates project properties
func UpdateProject(ctx context.Context, p *Project) error {
+ if !IsCardTypeValid(p.CardType) {
+ p.CardType = CardTypeTextOnly
+ }
+
_, err := db.GetEngine(ctx).ID(p.ID).Cols(
"title",
"description",
+ "card_type",
).Update(p)
return err
}
diff --git a/models/project/project_test.go b/models/project/project_test.go
index c2d9005c4..6caa244f5 100644
--- a/models/project/project_test.go
+++ b/models/project/project_test.go
@@ -53,6 +53,7 @@ func TestProject(t *testing.T) {
project := &Project{
Type: TypeRepository,
BoardType: BoardTypeBasicKanban,
+ CardType: CardTypeTextOnly,
Title: "New Project",
RepoID: 1,
CreatedUnix: timeutil.TimeStampNow(),
diff --git a/models/repo/attachment.go b/models/repo/attachment.go
index 8fbf79a7a..cb05386d9 100644
--- a/models/repo/attachment.go
+++ b/models/repo/attachment.go
@@ -132,6 +132,21 @@ func GetAttachmentsByIssueID(ctx context.Context, issueID int64) ([]*Attachment,
return attachments, db.GetEngine(ctx).Where("issue_id = ? AND comment_id = 0", issueID).Find(&attachments)
}
+// GetAttachmentsByIssueIDImagesLatest returns the latest image attachments of an issue.
+func GetAttachmentsByIssueIDImagesLatest(ctx context.Context, issueID int64) ([]*Attachment, error) {
+ attachments := make([]*Attachment, 0, 5)
+ return attachments, db.GetEngine(ctx).Where(`issue_id = ? AND (name like '%.apng'
+ OR name like '%.avif'
+ OR name like '%.bmp'
+ OR name like '%.gif'
+ OR name like '%.jpg'
+ OR name like '%.jpeg'
+ OR name like '%.jxl'
+ OR name like '%.png'
+ OR name like '%.svg'
+ OR name like '%.webp')`, issueID).Desc("comment_id").Limit(5).Find(&attachments)
+}
+
// GetAttachmentsByCommentID returns all attachments if comment by given ID.
func GetAttachmentsByCommentID(ctx context.Context, commentID int64) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10)