@@ -97,7 +97,7 @@ type Issue struct {
97
97
// TODO: RemoveIssueRef: see "repo/issue/branch_selector_field.tmpl"
98
98
Ref string
99
99
100
- PinOrder int `xorm:"DEFAULT 0"`
100
+ PinOrder int `xorm:"-"` // 0 means not loaded, -1 means loaded but not pinned
101
101
102
102
DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"`
103
103
@@ -291,6 +291,23 @@ func (issue *Issue) LoadMilestone(ctx context.Context) (err error) {
291
291
return nil
292
292
}
293
293
294
+ func (issue * Issue ) LoadPinOrder (ctx context.Context ) error {
295
+ if issue .PinOrder != 0 {
296
+ return nil
297
+ }
298
+ issuePin , err := GetIssuePin (ctx , issue )
299
+ if err != nil && ! db .IsErrNotExist (err ) {
300
+ return err
301
+ }
302
+
303
+ if issuePin != nil {
304
+ issue .PinOrder = issuePin .PinOrder
305
+ } else {
306
+ issue .PinOrder = - 1
307
+ }
308
+ return nil
309
+ }
310
+
294
311
// LoadAttributes loads the attribute of this issue.
295
312
func (issue * Issue ) LoadAttributes (ctx context.Context ) (err error ) {
296
313
if err = issue .LoadRepo (ctx ); err != nil {
@@ -330,6 +347,10 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
330
347
return err
331
348
}
332
349
350
+ if err = issue .LoadPinOrder (ctx ); err != nil {
351
+ return err
352
+ }
353
+
333
354
if err = issue .Comments .LoadAttributes (ctx ); err != nil {
334
355
return err
335
356
}
@@ -342,6 +363,14 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
342
363
return issue .loadReactions (ctx )
343
364
}
344
365
366
+ // IsPinned returns if a Issue is pinned
367
+ func (issue * Issue ) IsPinned () bool {
368
+ if issue .PinOrder == 0 {
369
+ setting .PanicInDevOrTesting ("issue's pinorder has not been loaded" )
370
+ }
371
+ return issue .PinOrder > 0
372
+ }
373
+
345
374
func (issue * Issue ) ResetAttributesLoaded () {
346
375
issue .isLabelsLoaded = false
347
376
issue .isMilestoneLoaded = false
@@ -720,190 +749,6 @@ func (issue *Issue) HasOriginalAuthor() bool {
720
749
return issue .OriginalAuthor != "" && issue .OriginalAuthorID != 0
721
750
}
722
751
723
- var ErrIssueMaxPinReached = util .NewInvalidArgumentErrorf ("the max number of pinned issues has been readched" )
724
-
725
- // IsPinned returns if a Issue is pinned
726
- func (issue * Issue ) IsPinned () bool {
727
- return issue .PinOrder != 0
728
- }
729
-
730
- // Pin pins a Issue
731
- func (issue * Issue ) Pin (ctx context.Context , user * user_model.User ) error {
732
- // If the Issue is already pinned, we don't need to pin it twice
733
- if issue .IsPinned () {
734
- return nil
735
- }
736
-
737
- var maxPin int
738
- _ , err := db .GetEngine (ctx ).SQL ("SELECT MAX(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ?" , issue .RepoID , issue .IsPull ).Get (& maxPin )
739
- if err != nil {
740
- return err
741
- }
742
-
743
- // Check if the maximum allowed Pins reached
744
- if maxPin >= setting .Repository .Issue .MaxPinned {
745
- return ErrIssueMaxPinReached
746
- }
747
-
748
- _ , err = db .GetEngine (ctx ).Table ("issue" ).
749
- Where ("id = ?" , issue .ID ).
750
- Update (map [string ]any {
751
- "pin_order" : maxPin + 1 ,
752
- })
753
- if err != nil {
754
- return err
755
- }
756
-
757
- // Add the pin event to the history
758
- opts := & CreateCommentOptions {
759
- Type : CommentTypePin ,
760
- Doer : user ,
761
- Repo : issue .Repo ,
762
- Issue : issue ,
763
- }
764
- if _ , err = CreateComment (ctx , opts ); err != nil {
765
- return err
766
- }
767
-
768
- return nil
769
- }
770
-
771
- // UnpinIssue unpins a Issue
772
- func (issue * Issue ) Unpin (ctx context.Context , user * user_model.User ) error {
773
- // If the Issue is not pinned, we don't need to unpin it
774
- if ! issue .IsPinned () {
775
- return nil
776
- }
777
-
778
- // This sets the Pin for all Issues that come after the unpined Issue to the correct value
779
- _ , err := db .GetEngine (ctx ).Exec ("UPDATE issue SET pin_order = pin_order - 1 WHERE repo_id = ? AND is_pull = ? AND pin_order > ?" , issue .RepoID , issue .IsPull , issue .PinOrder )
780
- if err != nil {
781
- return err
782
- }
783
-
784
- _ , err = db .GetEngine (ctx ).Table ("issue" ).
785
- Where ("id = ?" , issue .ID ).
786
- Update (map [string ]any {
787
- "pin_order" : 0 ,
788
- })
789
- if err != nil {
790
- return err
791
- }
792
-
793
- // Add the unpin event to the history
794
- opts := & CreateCommentOptions {
795
- Type : CommentTypeUnpin ,
796
- Doer : user ,
797
- Repo : issue .Repo ,
798
- Issue : issue ,
799
- }
800
- if _ , err = CreateComment (ctx , opts ); err != nil {
801
- return err
802
- }
803
-
804
- return nil
805
- }
806
-
807
- // PinOrUnpin pins or unpins a Issue
808
- func (issue * Issue ) PinOrUnpin (ctx context.Context , user * user_model.User ) error {
809
- if ! issue .IsPinned () {
810
- return issue .Pin (ctx , user )
811
- }
812
-
813
- return issue .Unpin (ctx , user )
814
- }
815
-
816
- // MovePin moves a Pinned Issue to a new Position
817
- func (issue * Issue ) MovePin (ctx context.Context , newPosition int ) error {
818
- // If the Issue is not pinned, we can't move them
819
- if ! issue .IsPinned () {
820
- return nil
821
- }
822
-
823
- if newPosition < 1 {
824
- return fmt .Errorf ("The Position can't be lower than 1" )
825
- }
826
-
827
- dbctx , committer , err := db .TxContext (ctx )
828
- if err != nil {
829
- return err
830
- }
831
- defer committer .Close ()
832
-
833
- var maxPin int
834
- _ , err = db .GetEngine (dbctx ).SQL ("SELECT MAX(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ?" , issue .RepoID , issue .IsPull ).Get (& maxPin )
835
- if err != nil {
836
- return err
837
- }
838
-
839
- // If the new Position bigger than the current Maximum, set it to the Maximum
840
- if newPosition > maxPin + 1 {
841
- newPosition = maxPin + 1
842
- }
843
-
844
- // Lower the Position of all Pinned Issue that came after the current Position
845
- _ , err = db .GetEngine (dbctx ).Exec ("UPDATE issue SET pin_order = pin_order - 1 WHERE repo_id = ? AND is_pull = ? AND pin_order > ?" , issue .RepoID , issue .IsPull , issue .PinOrder )
846
- if err != nil {
847
- return err
848
- }
849
-
850
- // Higher the Position of all Pinned Issues that comes after the new Position
851
- _ , err = db .GetEngine (dbctx ).Exec ("UPDATE issue SET pin_order = pin_order + 1 WHERE repo_id = ? AND is_pull = ? AND pin_order >= ?" , issue .RepoID , issue .IsPull , newPosition )
852
- if err != nil {
853
- return err
854
- }
855
-
856
- _ , err = db .GetEngine (dbctx ).Table ("issue" ).
857
- Where ("id = ?" , issue .ID ).
858
- Update (map [string ]any {
859
- "pin_order" : newPosition ,
860
- })
861
- if err != nil {
862
- return err
863
- }
864
-
865
- return committer .Commit ()
866
- }
867
-
868
- // GetPinnedIssues returns the pinned Issues for the given Repo and type
869
- func GetPinnedIssues (ctx context.Context , repoID int64 , isPull bool ) (IssueList , error ) {
870
- issues := make (IssueList , 0 )
871
-
872
- err := db .GetEngine (ctx ).
873
- Table ("issue" ).
874
- Where ("repo_id = ?" , repoID ).
875
- And ("is_pull = ?" , isPull ).
876
- And ("pin_order > 0" ).
877
- OrderBy ("pin_order" ).
878
- Find (& issues )
879
- if err != nil {
880
- return nil , err
881
- }
882
-
883
- err = issues .LoadAttributes (ctx )
884
- if err != nil {
885
- return nil , err
886
- }
887
-
888
- return issues , nil
889
- }
890
-
891
- // IsNewPinAllowed returns if a new Issue or Pull request can be pinned
892
- func IsNewPinAllowed (ctx context.Context , repoID int64 , isPull bool ) (bool , error ) {
893
- var maxPin int
894
- _ , err := db .GetEngine (ctx ).SQL ("SELECT COUNT(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ? AND pin_order > 0" , repoID , isPull ).Get (& maxPin )
895
- if err != nil {
896
- return false , err
897
- }
898
-
899
- return maxPin < setting .Repository .Issue .MaxPinned , nil
900
- }
901
-
902
- // IsErrIssueMaxPinReached returns if the error is, that the User can't pin more Issues
903
- func IsErrIssueMaxPinReached (err error ) bool {
904
- return err == ErrIssueMaxPinReached
905
- }
906
-
907
752
// InsertIssues insert issues to database
908
753
func InsertIssues (ctx context.Context , issues ... * Issue ) error {
909
754
ctx , committer , err := db .TxContext (ctx )
0 commit comments