mirror of
https://github.com/go-gitea/gitea.git
synced 2024-11-04 08:17:24 -05:00
Merge branch 'main' into oauth2-granular-scopes
This commit is contained in:
commit
667c8cc719
@ -386,7 +386,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||
return a.createAuthSource(ctx, authSource)
|
||||
}
|
||||
|
||||
// updateLdapBindDn updates a new LDAP (simple auth) authentication source.
|
||||
// updateLdapSimpleAuth updates a new LDAP (simple auth) authentication source.
|
||||
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
@ -907,6 +907,24 @@ LEVEL = Info
|
||||
;; Valid site url schemes for user profiles
|
||||
;VALID_SITE_URL_SCHEMES=http,https
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[service.explore]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Only allow signed in users to view the explore pages.
|
||||
;REQUIRE_SIGNIN_VIEW = false
|
||||
;;
|
||||
;; Disable the users explore page.
|
||||
;DISABLE_USERS_PAGE = false
|
||||
;;
|
||||
;; Disable the organizations explore page.
|
||||
;DISABLE_ORGANIZATIONS_PAGE = false
|
||||
;;
|
||||
;; Disable the code explore page.
|
||||
;DISABLE_CODE_PAGE = false
|
||||
;;
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
2
go.mod
2
go.mod
@ -54,7 +54,7 @@ require (
|
||||
github.com/go-chi/chi/v5 v5.0.13
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-co-op/gocron v1.37.0
|
||||
github.com/go-enry/go-enry/v2 v2.8.8
|
||||
github.com/go-enry/go-enry/v2 v2.9.1
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
|
4
go.sum
4
go.sum
@ -315,8 +315,8 @@ github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
|
||||
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
|
||||
github.com/go-enry/go-enry/v2 v2.8.8 h1:EhfxWpw4DQ3WEFB1Y77X8vKqZL0D0EDUUWYDUAIv9/4=
|
||||
github.com/go-enry/go-enry/v2 v2.8.8/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
|
||||
github.com/go-enry/go-enry/v2 v2.9.1 h1:G9iDteJ/Mc0F4Di5NeQknf83R2OkRbwY9cAYmcqVG6U=
|
||||
github.com/go-enry/go-enry/v2 v2.9.1/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
|
||||
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
|
||||
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
|
||||
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
||||
|
@ -63,6 +63,7 @@ type ProtectedBranch struct {
|
||||
RequireSignedCommits bool `xorm:"NOT NULL DEFAULT false"`
|
||||
ProtectedFilePatterns string `xorm:"TEXT"`
|
||||
UnprotectedFilePatterns string `xorm:"TEXT"`
|
||||
BlockAdminMergeOverride bool `xorm:"NOT NULL DEFAULT false"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
|
@ -872,7 +872,7 @@ func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) (IssueList,
|
||||
return issues, nil
|
||||
}
|
||||
|
||||
// IsNewPinnedAllowed returns if a new Issue or Pull request can be pinned
|
||||
// IsNewPinAllowed returns if a new Issue or Pull request can be pinned
|
||||
func IsNewPinAllowed(ctx context.Context, repoID int64, isPull bool) (bool, error) {
|
||||
var maxPin int
|
||||
_, 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)
|
||||
|
@ -701,7 +701,7 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest,
|
||||
return pr, pr.LoadAttributes(ctx)
|
||||
}
|
||||
|
||||
// GetPullRequestsByBaseHeadInfo returns the pull request by given base and head
|
||||
// GetPullRequestByBaseHeadInfo returns the pull request by given base and head
|
||||
func GetPullRequestByBaseHeadInfo(ctx context.Context, baseID, headID int64, base, head string) (*PullRequest, error) {
|
||||
pr := &PullRequest{}
|
||||
sess := db.GetEngine(ctx).
|
||||
|
@ -603,6 +603,8 @@ var migrations = []Migration{
|
||||
NewMigration("Add index for release sha1", v1_23.AddIndexForReleaseSha1),
|
||||
// v305 -> v306
|
||||
NewMigration("Add Repository Licenses", v1_23.AddRepositoryLicenses),
|
||||
// v306 -> v307
|
||||
NewMigration("Add BlockAdminMergeOverride to ProtectedBranch", v1_23.AddBlockAdminMergeOverrideBranchProtection),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current db version
|
||||
|
13
models/migrations/v1_23/v306.go
Normal file
13
models/migrations/v1_23/v306.go
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
func AddBlockAdminMergeOverrideBranchProtection(x *xorm.Engine) error {
|
||||
type ProtectedBranch struct {
|
||||
BlockAdminMergeOverride bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
return x.Sync(new(ProtectedBranch))
|
||||
}
|
@ -90,8 +90,10 @@ var Service = struct {
|
||||
|
||||
// Explore page settings
|
||||
Explore struct {
|
||||
RequireSigninView bool `ini:"REQUIRE_SIGNIN_VIEW"`
|
||||
DisableUsersPage bool `ini:"DISABLE_USERS_PAGE"`
|
||||
RequireSigninView bool `ini:"REQUIRE_SIGNIN_VIEW"`
|
||||
DisableUsersPage bool `ini:"DISABLE_USERS_PAGE"`
|
||||
DisableOrganizationsPage bool `ini:"DISABLE_ORGANIZATIONS_PAGE"`
|
||||
DisableCodePage bool `ini:"DISABLE_CODE_PAGE"`
|
||||
} `ini:"service.explore"`
|
||||
}{
|
||||
AllowedUserVisibilityModesSlice: []bool{true, true, true},
|
||||
|
@ -52,6 +52,7 @@ type BranchProtection struct {
|
||||
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
|
||||
BlockAdminMergeOverride bool `json:"block_admin_merge_override"`
|
||||
// swagger:strfmt date-time
|
||||
Created time.Time `json:"created_at"`
|
||||
// swagger:strfmt date-time
|
||||
@ -90,6 +91,7 @@ type CreateBranchProtectionOption struct {
|
||||
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
|
||||
BlockAdminMergeOverride bool `json:"block_admin_merge_override"`
|
||||
}
|
||||
|
||||
// EditBranchProtectionOption options for editing a branch protection
|
||||
@ -121,4 +123,5 @@ type EditBranchProtectionOption struct {
|
||||
RequireSignedCommits *bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns *string `json:"protected_file_patterns"`
|
||||
UnprotectedFilePatterns *string `json:"unprotected_file_patterns"`
|
||||
BlockAdminMergeOverride *bool `json:"block_admin_merge_override"`
|
||||
}
|
||||
|
@ -2462,6 +2462,8 @@ settings.block_on_official_review_requests = Block merge on official review requ
|
||||
settings.block_on_official_review_requests_desc = Merging will not be possible when it has official review requests, even if there are enough approvals.
|
||||
settings.block_outdated_branch = Block merge if pull request is outdated
|
||||
settings.block_outdated_branch_desc = Merging will not be possible when head branch is behind base branch.
|
||||
settings.block_admin_merge_override = Administrators must follow branch protection rules
|
||||
settings.block_admin_merge_override_desc = Administrators must follow branch protection rules and can not circumvent it.
|
||||
settings.default_branch_desc = Select a default repository branch for pull requests and code commits:
|
||||
settings.merge_style_desc = Merge Styles
|
||||
settings.default_merge_style_desc = Default Merge Style
|
||||
|
345
package-lock.json
generated
345
package-lock.json
generated
@ -55,7 +55,7 @@
|
||||
"typescript": "5.5.4",
|
||||
"uint8-to-base64": "0.2.0",
|
||||
"vanilla-colorful": "0.7.2",
|
||||
"vue": "3.4.38",
|
||||
"vue": "3.5.12",
|
||||
"vue-bar-graph": "2.1.0",
|
||||
"vue-chartjs": "5.3.1",
|
||||
"vue-loader": "17.4.2",
|
||||
@ -3618,224 +3618,208 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz",
|
||||
"integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz",
|
||||
"integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz",
|
||||
"integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz",
|
||||
"integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz",
|
||||
"integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz",
|
||||
"integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz",
|
||||
"integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz",
|
||||
"integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz",
|
||||
"integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz",
|
||||
"integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz",
|
||||
"integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz",
|
||||
"integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz",
|
||||
"integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz",
|
||||
"integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz",
|
||||
"integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz",
|
||||
"integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz",
|
||||
"integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz",
|
||||
"integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz",
|
||||
"integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz",
|
||||
"integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz",
|
||||
"integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz",
|
||||
"integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz",
|
||||
"integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz",
|
||||
"integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz",
|
||||
"integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz",
|
||||
"integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz",
|
||||
"integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@ -5202,113 +5186,130 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.38.tgz",
|
||||
"integrity": "sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz",
|
||||
"integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.24.7",
|
||||
"@vue/shared": "3.4.38",
|
||||
"@babel/parser": "^7.25.3",
|
||||
"@vue/shared": "3.5.12",
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.38.tgz",
|
||||
"integrity": "sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz",
|
||||
"integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/compiler-core": "3.5.12",
|
||||
"@vue/shared": "3.5.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz",
|
||||
"integrity": "sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz",
|
||||
"integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.24.7",
|
||||
"@vue/compiler-core": "3.4.38",
|
||||
"@vue/compiler-dom": "3.4.38",
|
||||
"@vue/compiler-ssr": "3.4.38",
|
||||
"@vue/shared": "3.4.38",
|
||||
"@babel/parser": "^7.25.3",
|
||||
"@vue/compiler-core": "3.5.12",
|
||||
"@vue/compiler-dom": "3.5.12",
|
||||
"@vue/compiler-ssr": "3.5.12",
|
||||
"@vue/shared": "3.5.12",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.10",
|
||||
"postcss": "^8.4.40",
|
||||
"magic-string": "^0.30.11",
|
||||
"postcss": "^8.4.47",
|
||||
"source-map-js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc/node_modules/magic-string": {
|
||||
"version": "0.30.11",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz",
|
||||
"integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
|
||||
"license": "MIT",
|
||||
"version": "0.30.12",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
|
||||
"integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.38.tgz",
|
||||
"integrity": "sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==",
|
||||
"license": "MIT",
|
||||
"node_modules/@vue/compiler-sfc/node_modules/postcss": {
|
||||
"version": "8.4.47",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
|
||||
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.1.0",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz",
|
||||
"integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.12",
|
||||
"@vue/shared": "3.5.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.38.tgz",
|
||||
"integrity": "sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz",
|
||||
"integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/shared": "3.5.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.38.tgz",
|
||||
"integrity": "sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz",
|
||||
"integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/reactivity": "3.5.12",
|
||||
"@vue/shared": "3.5.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.38.tgz",
|
||||
"integrity": "sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz",
|
||||
"integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.4.38",
|
||||
"@vue/runtime-core": "3.4.38",
|
||||
"@vue/shared": "3.4.38",
|
||||
"@vue/reactivity": "3.5.12",
|
||||
"@vue/runtime-core": "3.5.12",
|
||||
"@vue/shared": "3.5.12",
|
||||
"csstype": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.38.tgz",
|
||||
"integrity": "sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz",
|
||||
"integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/compiler-ssr": "3.5.12",
|
||||
"@vue/shared": "3.5.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.4.38"
|
||||
"vue": "3.5.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.38.tgz",
|
||||
"integrity": "sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==",
|
||||
"license": "MIT"
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz",
|
||||
"integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.12.1",
|
||||
@ -12460,10 +12461,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
||||
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
|
||||
"license": "ISC"
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
@ -13512,11 +13512,10 @@
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.79.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
|
||||
"integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
|
||||
"version": "2.79.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
|
||||
"integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
@ -13847,10 +13846,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||
"license": "BSD-3-Clause",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -15378,11 +15376,10 @@
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/vite/node_modules/@types/estree": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vite/node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
@ -15400,13 +15397,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/rollup": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz",
|
||||
"integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==",
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz",
|
||||
"integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.5"
|
||||
"@types/estree": "1.0.6"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
@ -15416,22 +15412,22 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.21.1",
|
||||
"@rollup/rollup-android-arm64": "4.21.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.21.1",
|
||||
"@rollup/rollup-darwin-x64": "4.21.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.21.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.21.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.21.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.21.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.21.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.21.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.21.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.21.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.21.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.21.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.21.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.24.0",
|
||||
"@rollup/rollup-android-arm64": "4.24.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.24.0",
|
||||
"@rollup/rollup-darwin-x64": "4.24.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.24.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.24.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.24.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.24.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.24.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.24.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.24.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@ -15560,16 +15556,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.38.tgz",
|
||||
"integrity": "sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==",
|
||||
"license": "MIT",
|
||||
"version": "3.5.12",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz",
|
||||
"integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.38",
|
||||
"@vue/compiler-sfc": "3.4.38",
|
||||
"@vue/runtime-dom": "3.4.38",
|
||||
"@vue/server-renderer": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/compiler-dom": "3.5.12",
|
||||
"@vue/compiler-sfc": "3.5.12",
|
||||
"@vue/runtime-dom": "3.5.12",
|
||||
"@vue/server-renderer": "3.5.12",
|
||||
"@vue/shared": "3.5.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
|
@ -54,7 +54,7 @@
|
||||
"typescript": "5.5.4",
|
||||
"uint8-to-base64": "0.2.0",
|
||||
"vanilla-colorful": "0.7.2",
|
||||
"vue": "3.4.38",
|
||||
"vue": "3.5.12",
|
||||
"vue-bar-graph": "2.1.0",
|
||||
"vue-chartjs": "5.3.1",
|
||||
"vue-loader": "17.4.2",
|
||||
|
@ -356,12 +356,20 @@ func reqToken() func(ctx *context.APIContext) {
|
||||
|
||||
func reqExploreSignIn() func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if setting.Service.Explore.RequireSigninView && !ctx.IsSigned {
|
||||
if (setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView) && !ctx.IsSigned {
|
||||
ctx.Error(http.StatusUnauthorized, "reqExploreSignIn", "you must be signed in to search for users")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func reqUsersExploreEnabled() func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if setting.Service.Explore.DisableUsersPage {
|
||||
ctx.NotFound()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if ctx.IsSigned && setting.Service.EnableReverseProxyAuthAPI && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName {
|
||||
@ -955,7 +963,7 @@ func Routes() *web.Router {
|
||||
|
||||
// Users (requires user scope)
|
||||
m.Group("/users", func() {
|
||||
m.Get("/search", reqExploreSignIn(), user.Search)
|
||||
m.Get("/search", reqExploreSignIn(), reqUsersExploreEnabled(), user.Search)
|
||||
|
||||
m.Group("/{username}", func() {
|
||||
m.Get("", reqExploreSignIn(), user.GetInfo)
|
||||
|
@ -642,6 +642,7 @@ func CreateBranchProtection(ctx *context.APIContext) {
|
||||
ProtectedFilePatterns: form.ProtectedFilePatterns,
|
||||
UnprotectedFilePatterns: form.UnprotectedFilePatterns,
|
||||
BlockOnOutdatedBranch: form.BlockOnOutdatedBranch,
|
||||
BlockAdminMergeOverride: form.BlockAdminMergeOverride,
|
||||
}
|
||||
|
||||
err = git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{
|
||||
@ -852,6 +853,10 @@ func EditBranchProtection(ctx *context.APIContext) {
|
||||
protectBranch.BlockOnOutdatedBranch = *form.BlockOnOutdatedBranch
|
||||
}
|
||||
|
||||
if form.BlockAdminMergeOverride != nil {
|
||||
protectBranch.BlockAdminMergeOverride = *form.BlockAdminMergeOverride
|
||||
}
|
||||
|
||||
var whitelistUsers, forcePushAllowlistUsers, mergeWhitelistUsers, approvalsWhitelistUsers []int64
|
||||
if form.PushWhitelistUsernames != nil {
|
||||
whitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.PushWhitelistUsernames, false)
|
||||
|
@ -41,80 +41,93 @@ func SearchIssues(ctx *context.APIContext) {
|
||||
// parameters:
|
||||
// - name: state
|
||||
// in: query
|
||||
// description: whether issue is open or closed
|
||||
// description: State of the issue
|
||||
// type: string
|
||||
// enum: [open, closed, all]
|
||||
// default: open
|
||||
// - name: labels
|
||||
// in: query
|
||||
// description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
|
||||
// description: Comma-separated list of label names. Fetch only issues that have any of these labels. Non existent labels are discarded.
|
||||
// type: string
|
||||
// - name: milestones
|
||||
// in: query
|
||||
// description: comma separated list of milestone names. Fetch only issues that have any of this milestones. Non existent are discarded
|
||||
// description: Comma-separated list of milestone names. Fetch only issues that have any of these milestones. Non existent milestones are discarded.
|
||||
// type: string
|
||||
// - name: q
|
||||
// in: query
|
||||
// description: search string
|
||||
// description: Search string
|
||||
// type: string
|
||||
// - name: priority_repo_id
|
||||
// in: query
|
||||
// description: repository to prioritize in the results
|
||||
// description: Repository ID to prioritize in the results
|
||||
// type: integer
|
||||
// format: int64
|
||||
// - name: type
|
||||
// in: query
|
||||
// description: filter by type (issues / pulls) if set
|
||||
// description: Filter by issue type
|
||||
// type: string
|
||||
// enum: [issues, pulls]
|
||||
// - name: since
|
||||
// in: query
|
||||
// description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
|
||||
// description: Only show issues updated after the given time (RFC 3339 format)
|
||||
// type: string
|
||||
// format: date-time
|
||||
// required: false
|
||||
// - name: before
|
||||
// in: query
|
||||
// description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
|
||||
// description: Only show issues updated before the given time (RFC 3339 format)
|
||||
// type: string
|
||||
// format: date-time
|
||||
// required: false
|
||||
// - name: assigned
|
||||
// in: query
|
||||
// description: filter (issues / pulls) assigned to you, default is false
|
||||
// description: Filter issues or pulls assigned to the authenticated user
|
||||
// type: boolean
|
||||
// default: false
|
||||
// - name: created
|
||||
// in: query
|
||||
// description: filter (issues / pulls) created by you, default is false
|
||||
// description: Filter issues or pulls created by the authenticated user
|
||||
// type: boolean
|
||||
// default: false
|
||||
// - name: mentioned
|
||||
// in: query
|
||||
// description: filter (issues / pulls) mentioning you, default is false
|
||||
// description: Filter issues or pulls mentioning the authenticated user
|
||||
// type: boolean
|
||||
// default: false
|
||||
// - name: review_requested
|
||||
// in: query
|
||||
// description: filter pulls requesting your review, default is false
|
||||
// description: Filter pull requests where the authenticated user's review was requested
|
||||
// type: boolean
|
||||
// default: false
|
||||
// - name: reviewed
|
||||
// in: query
|
||||
// description: filter pulls reviewed by you, default is false
|
||||
// description: Filter pull requests reviewed by the authenticated user
|
||||
// type: boolean
|
||||
// default: false
|
||||
// - name: owner
|
||||
// in: query
|
||||
// description: filter by owner
|
||||
// description: Filter by repository owner
|
||||
// type: string
|
||||
// - name: team
|
||||
// in: query
|
||||
// description: filter by team (requires organization owner parameter to be provided)
|
||||
// description: Filter by team (requires organization owner parameter)
|
||||
// type: string
|
||||
// - name: page
|
||||
// in: query
|
||||
// description: page number of results to return (1-based)
|
||||
// description: Page number of results to return (1-based)
|
||||
// type: integer
|
||||
// minimum: 1
|
||||
// default: 1
|
||||
// - name: limit
|
||||
// in: query
|
||||
// description: page size of results
|
||||
// description: Number of items per page
|
||||
// type: integer
|
||||
// minimum: 0
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/IssueList"
|
||||
// "400":
|
||||
// "$ref": "#/responses/error"
|
||||
// "422":
|
||||
// "$ref": "#/responses/validationError"
|
||||
|
||||
before, since, err := context.GetQueryBeforeSince(ctx.Base)
|
||||
if err != nil {
|
||||
|
@ -21,12 +21,13 @@ const (
|
||||
|
||||
// Code render explore code page
|
||||
func Code(ctx *context.Context) {
|
||||
if !setting.Indexer.RepoIndexerEnabled {
|
||||
if !setting.Indexer.RepoIndexerEnabled || setting.Service.Explore.DisableCodePage {
|
||||
ctx.Redirect(setting.AppSubURL + "/explore")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
|
||||
ctx.Data["UsersPageIsDisabled"] = setting.Service.Explore.DisableUsersPage
|
||||
ctx.Data["OrganizationsPageIsDisabled"] = setting.Service.Explore.DisableOrganizationsPage
|
||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||
ctx.Data["Title"] = ctx.Tr("explore")
|
||||
ctx.Data["PageIsExplore"] = true
|
||||
|
@ -14,7 +14,13 @@ import (
|
||||
|
||||
// Organizations render explore organizations page
|
||||
func Organizations(ctx *context.Context) {
|
||||
ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
|
||||
if setting.Service.Explore.DisableOrganizationsPage {
|
||||
ctx.Redirect(setting.AppSubURL + "/explore")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["UsersPageIsDisabled"] = setting.Service.Explore.DisableUsersPage
|
||||
ctx.Data["CodePageIsDisabled"] = setting.Service.Explore.DisableCodePage
|
||||
ctx.Data["Title"] = ctx.Tr("explore")
|
||||
ctx.Data["PageIsExplore"] = true
|
||||
ctx.Data["PageIsExploreOrganizations"] = true
|
||||
|
@ -165,7 +165,9 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
|
||||
|
||||
// Repos render explore repositories page
|
||||
func Repos(ctx *context.Context) {
|
||||
ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
|
||||
ctx.Data["UsersPageIsDisabled"] = setting.Service.Explore.DisableUsersPage
|
||||
ctx.Data["OrganizationsPageIsDisabled"] = setting.Service.Explore.DisableOrganizationsPage
|
||||
ctx.Data["CodePageIsDisabled"] = setting.Service.Explore.DisableCodePage
|
||||
ctx.Data["Title"] = ctx.Tr("explore")
|
||||
ctx.Data["PageIsExplore"] = true
|
||||
ctx.Data["PageIsExploreRepositories"] = true
|
||||
|
@ -131,9 +131,11 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions,
|
||||
// Users render explore users page
|
||||
func Users(ctx *context.Context) {
|
||||
if setting.Service.Explore.DisableUsersPage {
|
||||
ctx.Redirect(setting.AppSubURL + "/explore/repos")
|
||||
ctx.Redirect(setting.AppSubURL + "/explore")
|
||||
return
|
||||
}
|
||||
ctx.Data["OrganizationsPageIsDisabled"] = setting.Service.Explore.DisableOrganizationsPage
|
||||
ctx.Data["CodePageIsDisabled"] = setting.Service.Explore.DisableCodePage
|
||||
ctx.Data["Title"] = ctx.Tr("explore")
|
||||
ctx.Data["PageIsExplore"] = true
|
||||
ctx.Data["PageIsExploreUsers"] = true
|
||||
|
@ -256,6 +256,7 @@ func SettingsProtectedBranchPost(ctx *context.Context) {
|
||||
protectBranch.ProtectedFilePatterns = f.ProtectedFilePatterns
|
||||
protectBranch.UnprotectedFilePatterns = f.UnprotectedFilePatterns
|
||||
protectBranch.BlockOnOutdatedBranch = f.BlockOnOutdatedBranch
|
||||
protectBranch.BlockAdminMergeOverride = f.BlockAdminMergeOverride
|
||||
|
||||
err = git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{
|
||||
UserIDs: whitelistUsers,
|
||||
|
@ -8,37 +8,24 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
)
|
||||
|
||||
// Search search users
|
||||
func Search(ctx *context.Context) {
|
||||
listOptions := db.ListOptions{
|
||||
Page: ctx.FormInt("page"),
|
||||
PageSize: convert.ToCorrectPageSize(ctx.FormInt("limit")),
|
||||
}
|
||||
|
||||
users, maxResults, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{
|
||||
// SearchCandidates searches candidate users for dropdown list
|
||||
func SearchCandidates(ctx *context.Context) {
|
||||
users, _, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{
|
||||
Actor: ctx.Doer,
|
||||
Keyword: ctx.FormTrim("q"),
|
||||
UID: ctx.FormInt64("uid"),
|
||||
Type: user_model.UserTypeIndividual,
|
||||
IsActive: ctx.FormOptionalBool("active"),
|
||||
ListOptions: listOptions,
|
||||
IsActive: optional.Some(true),
|
||||
ListOptions: db.ListOptions{PageSize: setting.UI.MembersPagingNum},
|
||||
})
|
||||
if err != nil {
|
||||
ctx.JSON(http.StatusInternalServerError, map[string]any{
|
||||
"ok": false,
|
||||
"error": err.Error(),
|
||||
})
|
||||
ctx.ServerError("Unable to search users", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.SetTotalCountHeader(maxResults)
|
||||
|
||||
ctx.JSON(http.StatusOK, map[string]any{
|
||||
"ok": true,
|
||||
"data": convert.ToUsers(ctx, ctx.Doer, users),
|
||||
})
|
||||
ctx.JSON(http.StatusOK, map[string]any{"data": convert.ToUsers(ctx, ctx.Doer, users)})
|
||||
}
|
||||
|
@ -39,8 +39,9 @@ func RegenerateScratchTwoFactor(ctx *context.Context) {
|
||||
if auth.IsErrTwoFactorNotEnrolled(err) {
|
||||
ctx.Flash.Error(ctx.Tr("settings.twofa_not_enrolled"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
} else {
|
||||
ctx.ServerError("SettingsTwoFactor: Failed to GetTwoFactorByUID", err)
|
||||
}
|
||||
ctx.ServerError("SettingsTwoFactor: Failed to GetTwoFactorByUID", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -74,8 +75,9 @@ func DisableTwoFactor(ctx *context.Context) {
|
||||
if auth.IsErrTwoFactorNotEnrolled(err) {
|
||||
ctx.Flash.Error(ctx.Tr("settings.twofa_not_enrolled"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
} else {
|
||||
ctx.ServerError("SettingsTwoFactor: Failed to GetTwoFactorByUID", err)
|
||||
}
|
||||
ctx.ServerError("SettingsTwoFactor: Failed to GetTwoFactorByUID", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -84,8 +86,9 @@ func DisableTwoFactor(ctx *context.Context) {
|
||||
// There is a potential DB race here - we must have been disabled by another request in the intervening period
|
||||
ctx.Flash.Success(ctx.Tr("settings.twofa_disabled"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
} else {
|
||||
ctx.ServerError("SettingsTwoFactor: Failed to DeleteTwoFactorByID", err)
|
||||
}
|
||||
ctx.ServerError("SettingsTwoFactor: Failed to DeleteTwoFactorByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -670,7 +670,7 @@ func registerRoutes(m *web.Router) {
|
||||
m.Post("/forgot_password", auth.ForgotPasswdPost)
|
||||
m.Post("/logout", auth.SignOut)
|
||||
m.Get("/stopwatches", reqSignIn, user.GetStopwatches)
|
||||
m.Get("/search", ignExploreSignIn, user.Search)
|
||||
m.Get("/search_candidates", ignExploreSignIn, user.SearchCandidates)
|
||||
m.Group("/oauth2", func() {
|
||||
m.Get("/{provider}", auth.SignInOAuth)
|
||||
m.Get("/{provider}/callback", auth.SignInOAuthCallback)
|
||||
|
@ -185,6 +185,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
|
||||
RequireSignedCommits: bp.RequireSignedCommits,
|
||||
ProtectedFilePatterns: bp.ProtectedFilePatterns,
|
||||
UnprotectedFilePatterns: bp.UnprotectedFilePatterns,
|
||||
BlockAdminMergeOverride: bp.BlockAdminMergeOverride,
|
||||
Created: bp.CreatedUnix.AsTime(),
|
||||
Updated: bp.UpdatedUnix.AsTime(),
|
||||
}
|
||||
|
@ -219,6 +219,7 @@ type ProtectBranchForm struct {
|
||||
RequireSignedCommits bool
|
||||
ProtectedFilePatterns string
|
||||
UnprotectedFilePatterns string
|
||||
BlockAdminMergeOverride bool
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
|
@ -68,7 +68,7 @@ const (
|
||||
)
|
||||
|
||||
// CheckPullMergeable check if the pull mergeable based on all conditions (branch protection, merge options, ...)
|
||||
func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error {
|
||||
func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminForceMerge bool) error {
|
||||
return db.WithTx(stdCtx, func(ctx context.Context) error {
|
||||
if pr.HasMerged {
|
||||
return ErrHasMerged
|
||||
@ -118,13 +118,22 @@ func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *acc
|
||||
err = nil
|
||||
}
|
||||
|
||||
// * if the doer is admin, they could skip the branch protection check
|
||||
if adminSkipProtectionCheck {
|
||||
if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil {
|
||||
log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, errCheckAdmin)
|
||||
return errCheckAdmin
|
||||
} else if isRepoAdmin {
|
||||
err = nil // repo admin can skip the check, so clear the error
|
||||
// * if admin tries to "Force Merge", they could sometimes skip the branch protection check
|
||||
if adminForceMerge {
|
||||
isRepoAdmin, errForceMerge := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer)
|
||||
if errForceMerge != nil {
|
||||
return fmt.Errorf("IsUserRepoAdmin failed, repo: %v, doer: %v, err: %w", pr.BaseRepoID, doer.ID, errForceMerge)
|
||||
}
|
||||
|
||||
protectedBranchRule, errForceMerge := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if errForceMerge != nil {
|
||||
return fmt.Errorf("GetFirstMatchProtectedBranchRule failed, repo: %v, base branch: %v, err: %w", pr.BaseRepoID, pr.BaseBranch, errForceMerge)
|
||||
}
|
||||
|
||||
// if doer is admin and the "Force Merge" is not blocked, then clear the branch protection check error
|
||||
blockAdminForceMerge := protectedBranchRule != nil && protectedBranchRule.BlockAdminMergeOverride
|
||||
if isRepoAdmin && !blockAdminForceMerge {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,6 +289,7 @@ func DeleteInactiveUsers(ctx context.Context, olderThan time.Duration) error {
|
||||
if err = DeleteUser(ctx, u, false); err != nil {
|
||||
// Ignore inactive users that were ever active but then were set inactive by admin
|
||||
if models.IsErrUserOwnRepos(err) || models.IsErrUserHasOrgs(err) || models.IsErrUserOwnPackages(err) {
|
||||
log.Warn("Inactive user %q has repositories, organizations or packages, skipping deletion: %v", u.Name, err)
|
||||
continue
|
||||
}
|
||||
select {
|
||||
|
@ -3,15 +3,17 @@
|
||||
<a class="{{if .PageIsExploreRepositories}}active {{end}}item" href="{{AppSubUrl}}/explore/repos">
|
||||
{{svg "octicon-repo"}} {{ctx.Locale.Tr "explore.repos"}}
|
||||
</a>
|
||||
{{if not .UsersIsDisabled}}
|
||||
{{if not .UsersPageIsDisabled}}
|
||||
<a class="{{if .PageIsExploreUsers}}active {{end}}item" href="{{AppSubUrl}}/explore/users">
|
||||
{{svg "octicon-person"}} {{ctx.Locale.Tr "explore.users"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if not .OrganizationsPageIsDisabled}}
|
||||
<a class="{{if .PageIsExploreOrganizations}}active {{end}}item" href="{{AppSubUrl}}/explore/organizations">
|
||||
{{svg "octicon-organization"}} {{ctx.Locale.Tr "explore.organizations"}}
|
||||
</a>
|
||||
{{if and (not ctx.Consts.RepoUnitTypeCode.UnitGlobalDisabled) .IsRepoIndexerEnabled}}
|
||||
{{end}}
|
||||
{{if and (not ctx.Consts.RepoUnitTypeCode.UnitGlobalDisabled) .IsRepoIndexerEnabled (not .CodePageIsDisabled)}}
|
||||
<a class="{{if .PageIsExploreCode}}active {{end}}item" href="{{AppSubUrl}}/explore/code">
|
||||
{{svg "octicon-code"}} {{ctx.Locale.Tr "explore.code"}}
|
||||
</a>
|
||||
|
@ -164,7 +164,7 @@
|
||||
{{$notAllOverridableChecksOk := or .IsBlockedByApprovals .IsBlockedByRejection .IsBlockedByOfficialReviewRequests .IsBlockedByOutdatedBranch .IsBlockedByChangedProtectedFiles (and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess))}}
|
||||
|
||||
{{/* admin can merge without checks, writer can merge when checks succeed */}}
|
||||
{{$canMergeNow := and (or $.IsRepoAdmin (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}}
|
||||
{{$canMergeNow := and (or (and (not $.ProtectedBranch.BlockAdminMergeOverride) $.IsRepoAdmin) (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}}
|
||||
{{/* admin and writer both can make an auto merge schedule */}}
|
||||
|
||||
{{if $canMergeNow}}
|
||||
|
@ -323,6 +323,13 @@
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.block_outdated_branch_desc"}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="block_admin_merge_override" type="checkbox" {{if .Rule.BlockAdminMergeOverride}}checked{{end}}>
|
||||
<label>{{ctx.Locale.Tr "repo.settings.block_admin_merge_override"}}</label>
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.block_admin_merge_override_desc"}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="field">
|
||||
|
70
templates/swagger/v1_json.tmpl
generated
70
templates/swagger/v1_json.tmpl
generated
@ -3444,107 +3444,125 @@
|
||||
"operationId": "issueSearchIssues",
|
||||
"parameters": [
|
||||
{
|
||||
"enum": [
|
||||
"open",
|
||||
"closed",
|
||||
"all"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "whether issue is open or closed",
|
||||
"default": "open",
|
||||
"description": "State of the issue",
|
||||
"name": "state",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded",
|
||||
"description": "Comma-separated list of label names. Fetch only issues that have any of these labels. Non existent labels are discarded.",
|
||||
"name": "labels",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "comma separated list of milestone names. Fetch only issues that have any of this milestones. Non existent are discarded",
|
||||
"description": "Comma-separated list of milestone names. Fetch only issues that have any of these milestones. Non existent milestones are discarded.",
|
||||
"name": "milestones",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "search string",
|
||||
"description": "Search string",
|
||||
"name": "q",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "repository to prioritize in the results",
|
||||
"description": "Repository ID to prioritize in the results",
|
||||
"name": "priority_repo_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"issues",
|
||||
"pulls"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "filter by type (issues / pulls) if set",
|
||||
"description": "Filter by issue type",
|
||||
"name": "type",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Only show notifications updated after the given time. This is a timestamp in RFC 3339 format",
|
||||
"description": "Only show issues updated after the given time (RFC 3339 format)",
|
||||
"name": "since",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Only show notifications updated before the given time. This is a timestamp in RFC 3339 format",
|
||||
"description": "Only show issues updated before the given time (RFC 3339 format)",
|
||||
"name": "before",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "filter (issues / pulls) assigned to you, default is false",
|
||||
"default": false,
|
||||
"description": "Filter issues or pulls assigned to the authenticated user",
|
||||
"name": "assigned",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "filter (issues / pulls) created by you, default is false",
|
||||
"default": false,
|
||||
"description": "Filter issues or pulls created by the authenticated user",
|
||||
"name": "created",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "filter (issues / pulls) mentioning you, default is false",
|
||||
"default": false,
|
||||
"description": "Filter issues or pulls mentioning the authenticated user",
|
||||
"name": "mentioned",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "filter pulls requesting your review, default is false",
|
||||
"default": false,
|
||||
"description": "Filter pull requests where the authenticated user's review was requested",
|
||||
"name": "review_requested",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "filter pulls reviewed by you, default is false",
|
||||
"default": false,
|
||||
"description": "Filter pull requests reviewed by the authenticated user",
|
||||
"name": "reviewed",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "filter by owner",
|
||||
"description": "Filter by repository owner",
|
||||
"name": "owner",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "filter by team (requires organization owner parameter to be provided)",
|
||||
"description": "Filter by team (requires organization owner parameter)",
|
||||
"name": "team",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "page number of results to return (1-based)",
|
||||
"default": 1,
|
||||
"description": "Page number of results to return (1-based)",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"minimum": 0,
|
||||
"type": "integer",
|
||||
"description": "page size of results",
|
||||
"description": "Number of items per page",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
@ -3552,6 +3570,12 @@
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/IssueList"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/responses/error"
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/responses/validationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18747,6 +18771,10 @@
|
||||
},
|
||||
"x-go-name": "ApprovalsWhitelistUsernames"
|
||||
},
|
||||
"block_admin_merge_override": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "BlockAdminMergeOverride"
|
||||
},
|
||||
"block_on_official_review_requests": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "BlockOnOfficialReviewRequests"
|
||||
@ -19442,6 +19470,10 @@
|
||||
},
|
||||
"x-go-name": "ApprovalsWhitelistUsernames"
|
||||
},
|
||||
"block_admin_merge_override": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "BlockAdminMergeOverride"
|
||||
},
|
||||
"block_on_official_review_requests": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "BlockOnOfficialReviewRequests"
|
||||
@ -20661,6 +20693,10 @@
|
||||
},
|
||||
"x-go-name": "ApprovalsWhitelistUsernames"
|
||||
},
|
||||
"block_admin_merge_override": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "BlockAdminMergeOverride"
|
||||
},
|
||||
"block_on_official_review_requests": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "BlockOnOfficialReviewRequests"
|
||||
|
@ -976,3 +976,50 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing.
|
||||
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
|
||||
})
|
||||
}
|
||||
|
||||
func TestPullNonMergeForAdminWithBranchProtection(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
// create a pull request
|
||||
session := loginUser(t, "user1")
|
||||
forkedName := "repo1-1"
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", forkedName, "")
|
||||
defer testDeleteRepository(t, session, "user1", forkedName)
|
||||
|
||||
testEditFile(t, session, "user1", forkedName, "master", "README.md", "Hello, World (Edited)\n")
|
||||
testPullCreate(t, session, "user1", forkedName, false, "master", "master", "Indexer notifier test pull")
|
||||
|
||||
baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
|
||||
forkedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: forkedName})
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
|
||||
BaseRepoID: baseRepo.ID,
|
||||
BaseBranch: "master",
|
||||
HeadRepoID: forkedRepo.ID,
|
||||
HeadBranch: "master",
|
||||
})
|
||||
|
||||
// add protected branch for commit status
|
||||
csrf := GetUserCSRFToken(t, session)
|
||||
// Change master branch to protected
|
||||
pbCreateReq := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"rule_name": "master",
|
||||
"enable_push": "true",
|
||||
"enable_status_check": "true",
|
||||
"status_check_contexts": "gitea/actions",
|
||||
"block_admin_merge_override": "true",
|
||||
})
|
||||
session.MakeRequest(t, pbCreateReq, http.StatusSeeOther)
|
||||
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
|
||||
mergeReq := NewRequestWithValues(t, "POST", "/api/v1/repos/user2/repo1/pulls/6/merge", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"head_commit_id": "",
|
||||
"merge_when_checks_succeed": "false",
|
||||
"force_merge": "true",
|
||||
"do": "rebase",
|
||||
}).AddTokenAuth(token)
|
||||
|
||||
session.MakeRequest(t, mergeReq, http.StatusMethodNotAllowed)
|
||||
})
|
||||
}
|
||||
|
@ -3,14 +3,19 @@ import '@github/text-expander-element';
|
||||
import $ from 'jquery';
|
||||
import {attachTribute} from '../tribute.ts';
|
||||
import {hideElem, showElem, autosize, isElemVisible} from '../../utils/dom.ts';
|
||||
import {initEasyMDEPaste, initTextareaEvents} from './EditorUpload.ts';
|
||||
import {
|
||||
EventUploadStateChanged,
|
||||
initEasyMDEPaste,
|
||||
initTextareaEvents,
|
||||
triggerUploadStateChanged,
|
||||
} from './EditorUpload.ts';
|
||||
import {handleGlobalEnterQuickSubmit} from './QuickSubmit.ts';
|
||||
import {renderPreviewPanelContent} from '../repo-editor.ts';
|
||||
import {easyMDEToolbarActions} from './EasyMDEToolbarActions.ts';
|
||||
import {initTextExpander} from './TextExpander.ts';
|
||||
import {showErrorToast} from '../../modules/toast.ts';
|
||||
import {POST} from '../../modules/fetch.ts';
|
||||
import {initTextareaMarkdown} from './EditorMarkdown.ts';
|
||||
import {EventEditorContentChanged, initTextareaMarkdown, triggerEditorContentChanged} from './EditorMarkdown.ts';
|
||||
import {DropzoneCustomEventReloadFiles, initDropzone} from '../dropzone.ts';
|
||||
|
||||
let elementIdCounter = 0;
|
||||
@ -37,7 +42,34 @@ export function validateTextareaNonEmpty(textarea) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class ComboMarkdownEditor {
|
||||
export class ComboMarkdownEditor {
|
||||
static EventEditorContentChanged = EventEditorContentChanged;
|
||||
static EventUploadStateChanged = EventUploadStateChanged;
|
||||
|
||||
public container : HTMLElement;
|
||||
|
||||
// TODO: use correct types to replace these "any" types
|
||||
options: any;
|
||||
|
||||
tabEditor: HTMLElement;
|
||||
tabPreviewer: HTMLElement;
|
||||
|
||||
easyMDE: any;
|
||||
easyMDEToolbarActions: any;
|
||||
easyMDEToolbarDefault: any;
|
||||
|
||||
textarea: HTMLTextAreaElement & {_giteaComboMarkdownEditor: any};
|
||||
textareaMarkdownToolbar: HTMLElement;
|
||||
textareaAutosize: any;
|
||||
|
||||
dropzone: HTMLElement;
|
||||
attachedDropzoneInst: any;
|
||||
|
||||
previewUrl: string;
|
||||
previewContext: string;
|
||||
previewMode: string;
|
||||
previewWiki: boolean;
|
||||
|
||||
constructor(container, options = {}) {
|
||||
container._giteaComboMarkdownEditor = this;
|
||||
this.options = options;
|
||||
@ -63,14 +95,13 @@ class ComboMarkdownEditor {
|
||||
|
||||
setupContainer() {
|
||||
initTextExpander(this.container.querySelector('text-expander'));
|
||||
this.container.addEventListener('ce-editor-content-changed', (e) => this.options?.onContentChanged?.(this, e));
|
||||
}
|
||||
|
||||
setupTextarea() {
|
||||
this.textarea = this.container.querySelector('.markdown-text-editor');
|
||||
this.textarea._giteaComboMarkdownEditor = this;
|
||||
this.textarea.id = `_combo_markdown_editor_${String(elementIdCounter++)}`;
|
||||
this.textarea.addEventListener('input', (e) => this.options?.onContentChanged?.(this, e));
|
||||
this.textarea.addEventListener('input', () => triggerEditorContentChanged(this.container));
|
||||
this.applyEditorHeights(this.textarea, this.options.editorHeights);
|
||||
|
||||
if (this.textarea.getAttribute('data-disable-autosize') !== 'true') {
|
||||
@ -115,15 +146,21 @@ class ComboMarkdownEditor {
|
||||
|
||||
async setupDropzone() {
|
||||
const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container');
|
||||
if (dropzoneParentContainer) {
|
||||
this.dropzone = this.container.closest(this.container.getAttribute('data-dropzone-parent-container'))?.querySelector('.dropzone');
|
||||
if (this.dropzone) this.attachedDropzoneInst = await initDropzone(this.dropzone);
|
||||
}
|
||||
if (!dropzoneParentContainer) return;
|
||||
this.dropzone = this.container.closest(this.container.getAttribute('data-dropzone-parent-container'))?.querySelector('.dropzone');
|
||||
if (!this.dropzone) return;
|
||||
|
||||
this.attachedDropzoneInst = await initDropzone(this.dropzone);
|
||||
// dropzone events
|
||||
// * "processing" means a file is being uploaded
|
||||
// * "queuecomplete" means all files have been uploaded
|
||||
this.attachedDropzoneInst.on('processing', () => triggerUploadStateChanged(this.container));
|
||||
this.attachedDropzoneInst.on('queuecomplete', () => triggerUploadStateChanged(this.container));
|
||||
}
|
||||
|
||||
dropzoneGetFiles() {
|
||||
if (!this.dropzone) return null;
|
||||
return Array.from(this.dropzone.querySelectorAll('.files [name=files]'), (el) => el.value);
|
||||
return Array.from(this.dropzone.querySelectorAll<HTMLInputElement>('.files [name=files]'), (el) => el.value);
|
||||
}
|
||||
|
||||
dropzoneReloadFiles() {
|
||||
@ -137,8 +174,13 @@ class ComboMarkdownEditor {
|
||||
this.attachedDropzoneInst.emit(DropzoneCustomEventReloadFiles);
|
||||
}
|
||||
|
||||
isUploading() {
|
||||
if (!this.dropzone) return false;
|
||||
return this.attachedDropzoneInst.getQueuedFiles().length || this.attachedDropzoneInst.getUploadingFiles().length;
|
||||
}
|
||||
|
||||
setupTab() {
|
||||
const tabs = this.container.querySelectorAll('.tabular.menu > .item');
|
||||
const tabs = this.container.querySelectorAll<HTMLElement>('.tabular.menu > .item');
|
||||
|
||||
// Fomantic Tab requires the "data-tab" to be globally unique.
|
||||
// So here it uses our defined "data-tab-for" and "data-tab-panel" to generate the "data-tab" attribute for Fomantic.
|
||||
@ -170,7 +212,7 @@ class ComboMarkdownEditor {
|
||||
formData.append('mode', this.previewMode);
|
||||
formData.append('context', this.previewContext);
|
||||
formData.append('text', this.value());
|
||||
formData.append('wiki', this.previewWiki);
|
||||
formData.append('wiki', String(this.previewWiki));
|
||||
const response = await POST(this.previewUrl, {data: formData});
|
||||
const data = await response.text();
|
||||
renderPreviewPanelContent($(panelPreviewer), data);
|
||||
@ -237,24 +279,24 @@ class ComboMarkdownEditor {
|
||||
easyMDEOpt.toolbar = this.parseEasyMDEToolbar(EasyMDE, easyMDEOpt.toolbar ?? this.easyMDEToolbarDefault);
|
||||
|
||||
this.easyMDE = new EasyMDE(easyMDEOpt);
|
||||
this.easyMDE.codemirror.on('change', (...args) => {this.options?.onContentChanged?.(this, ...args)});
|
||||
this.easyMDE.codemirror.on('change', () => triggerEditorContentChanged(this.container));
|
||||
this.easyMDE.codemirror.setOption('extraKeys', {
|
||||
'Cmd-Enter': (cm) => handleGlobalEnterQuickSubmit(cm.getTextArea()),
|
||||
'Ctrl-Enter': (cm) => handleGlobalEnterQuickSubmit(cm.getTextArea()),
|
||||
Enter: (cm) => {
|
||||
const tributeContainer = document.querySelector('.tribute-container');
|
||||
const tributeContainer = document.querySelector<HTMLElement>('.tribute-container');
|
||||
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
||||
cm.execCommand('newlineAndIndent');
|
||||
}
|
||||
},
|
||||
Up: (cm) => {
|
||||
const tributeContainer = document.querySelector('.tribute-container');
|
||||
const tributeContainer = document.querySelector<HTMLElement>('.tribute-container');
|
||||
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
||||
return cm.execCommand('goLineUp');
|
||||
}
|
||||
},
|
||||
Down: (cm) => {
|
||||
const tributeContainer = document.querySelector('.tribute-container');
|
||||
const tributeContainer = document.querySelector<HTMLElement>('.tribute-container');
|
||||
if (!tributeContainer || tributeContainer.style.display === 'none') {
|
||||
return cm.execCommand('goLineDown');
|
||||
}
|
||||
@ -314,13 +356,7 @@ export function getComboMarkdownEditor(el) {
|
||||
return el?._giteaComboMarkdownEditor;
|
||||
}
|
||||
|
||||
export async function initComboMarkdownEditor(container, options = {}) {
|
||||
if (container instanceof $) {
|
||||
if (container.length !== 1) {
|
||||
throw new Error('initComboMarkdownEditor: container must be a single element');
|
||||
}
|
||||
container = container[0];
|
||||
}
|
||||
export async function initComboMarkdownEditor(container: HTMLElement, options = {}) {
|
||||
if (!container) {
|
||||
throw new Error('initComboMarkdownEditor: container is null');
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
export const EventEditorContentChanged = 'ce-editor-content-changed';
|
||||
|
||||
export function triggerEditorContentChanged(target) {
|
||||
target.dispatchEvent(new CustomEvent('ce-editor-content-changed', {bubbles: true}));
|
||||
target.dispatchEvent(new CustomEvent(EventEditorContentChanged, {bubbles: true}));
|
||||
}
|
||||
|
||||
function handleIndentSelection(textarea, e) {
|
||||
|
@ -7,9 +7,16 @@ import {
|
||||
DropzoneCustomEventUploadDone,
|
||||
generateMarkdownLinkForAttachment,
|
||||
} from '../dropzone.ts';
|
||||
import type CodeMirror from 'codemirror';
|
||||
|
||||
let uploadIdCounter = 0;
|
||||
|
||||
export const EventUploadStateChanged = 'ce-upload-state-changed';
|
||||
|
||||
export function triggerUploadStateChanged(target) {
|
||||
target.dispatchEvent(new CustomEvent(EventUploadStateChanged, {bubbles: true}));
|
||||
}
|
||||
|
||||
function uploadFile(dropzoneEl, file) {
|
||||
return new Promise((resolve) => {
|
||||
const curUploadId = uploadIdCounter++;
|
||||
@ -18,7 +25,7 @@ function uploadFile(dropzoneEl, file) {
|
||||
const onUploadDone = ({file}) => {
|
||||
if (file._giteaUploadId === curUploadId) {
|
||||
dropzoneInst.off(DropzoneCustomEventUploadDone, onUploadDone);
|
||||
resolve();
|
||||
resolve(file);
|
||||
}
|
||||
};
|
||||
dropzoneInst.on(DropzoneCustomEventUploadDone, onUploadDone);
|
||||
@ -27,6 +34,8 @@ function uploadFile(dropzoneEl, file) {
|
||||
}
|
||||
|
||||
class TextareaEditor {
|
||||
editor : HTMLTextAreaElement;
|
||||
|
||||
constructor(editor) {
|
||||
this.editor = editor;
|
||||
}
|
||||
@ -61,6 +70,8 @@ class TextareaEditor {
|
||||
}
|
||||
|
||||
class CodeMirrorEditor {
|
||||
editor: CodeMirror.EditorFromTextArea;
|
||||
|
||||
constructor(editor) {
|
||||
this.editor = editor;
|
||||
}
|
||||
|
@ -8,41 +8,38 @@ export function initCompSearchUserBox() {
|
||||
const searchUserBox = document.querySelector('#search-user-box');
|
||||
if (!searchUserBox) return;
|
||||
|
||||
const $searchUserBox = $(searchUserBox);
|
||||
const allowEmailInput = searchUserBox.getAttribute('data-allow-email') === 'true';
|
||||
const allowEmailDescription = searchUserBox.getAttribute('data-allow-email-description') ?? undefined;
|
||||
$searchUserBox.search({
|
||||
$(searchUserBox).search({
|
||||
minCharacters: 2,
|
||||
apiSettings: {
|
||||
url: `${appSubUrl}/user/search?active=1&q={query}`,
|
||||
url: `${appSubUrl}/user/search_candidates?q={query}`,
|
||||
onResponse(response) {
|
||||
const items = [];
|
||||
const searchQuery = $searchUserBox.find('input').val();
|
||||
const resultItems = [];
|
||||
const searchQuery = searchUserBox.querySelector('input').value;
|
||||
const searchQueryUppercase = searchQuery.toUpperCase();
|
||||
$.each(response.data, (_i, item) => {
|
||||
for (const item of response.data) {
|
||||
const resultItem = {
|
||||
title: item.login,
|
||||
image: item.avatar_url,
|
||||
description: htmlEscape(item.full_name),
|
||||
};
|
||||
if (item.full_name) {
|
||||
resultItem.description = htmlEscape(item.full_name);
|
||||
}
|
||||
if (searchQueryUppercase === item.login.toUpperCase()) {
|
||||
items.unshift(resultItem);
|
||||
resultItems.unshift(resultItem); // add the exact match to the top
|
||||
} else {
|
||||
items.push(resultItem);
|
||||
resultItems.push(resultItem);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (allowEmailInput && !items.length && looksLikeEmailAddressCheck.test(searchQuery)) {
|
||||
if (allowEmailInput && !resultItems.length && looksLikeEmailAddressCheck.test(searchQuery)) {
|
||||
const resultItem = {
|
||||
title: searchQuery,
|
||||
description: allowEmailDescription,
|
||||
};
|
||||
items.push(resultItem);
|
||||
resultItems.push(resultItem);
|
||||
}
|
||||
|
||||
return {results: items};
|
||||
return {results: resultItems};
|
||||
},
|
||||
},
|
||||
searchFields: ['login', 'full_name'],
|
||||
|
@ -128,10 +128,12 @@ export async function initDropzone(dropzoneEl) {
|
||||
fileUuidDict = {};
|
||||
for (const attachment of respData) {
|
||||
const file = {name: attachment.name, uuid: attachment.uuid, size: attachment.size};
|
||||
const imgSrc = `${attachmentBaseLinkUrl}/${file.uuid}`;
|
||||
dzInst.emit('addedfile', file);
|
||||
dzInst.emit('thumbnail', file, imgSrc);
|
||||
dzInst.emit('complete', file);
|
||||
if (isImageFile(file.name)) {
|
||||
const imgSrc = `${attachmentBaseLinkUrl}/${file.uuid}`;
|
||||
dzInst.emit('thumbnail', file, imgSrc);
|
||||
}
|
||||
addCopyLink(file); // it is from server response, so no "type"
|
||||
fileUuidDict[file.uuid] = {submitted: true};
|
||||
const input = createElementFromAttrs('input', {name: 'files', type: 'hidden', id: `dropzone-file-${file.uuid}`, value: file.uuid});
|
||||
|
@ -1,11 +1,12 @@
|
||||
import $ from 'jquery';
|
||||
import {handleReply} from './repo-issue.ts';
|
||||
import {getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
||||
import {getComboMarkdownEditor, initComboMarkdownEditor, ComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
||||
import {POST} from '../modules/fetch.ts';
|
||||
import {showErrorToast} from '../modules/toast.ts';
|
||||
import {hideElem, showElem} from '../utils/dom.ts';
|
||||
import {attachRefIssueContextPopup} from './contextpopup.ts';
|
||||
import {initCommentContent, initMarkupContent} from '../markup/content.ts';
|
||||
import {triggerUploadStateChanged} from './comp/EditorUpload.ts';
|
||||
|
||||
async function onEditContent(event) {
|
||||
event.preventDefault();
|
||||
@ -15,7 +16,7 @@ async function onEditContent(event) {
|
||||
const renderContent = segment.querySelector('.render-content');
|
||||
const rawContent = segment.querySelector('.raw-content');
|
||||
|
||||
let comboMarkdownEditor;
|
||||
let comboMarkdownEditor : ComboMarkdownEditor;
|
||||
|
||||
const cancelAndReset = (e) => {
|
||||
e.preventDefault();
|
||||
@ -79,9 +80,12 @@ async function onEditContent(event) {
|
||||
comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
|
||||
if (!comboMarkdownEditor) {
|
||||
editContentZone.innerHTML = document.querySelector('#issue-comment-editor-template').innerHTML;
|
||||
const saveButton = editContentZone.querySelector('.ui.primary.button');
|
||||
comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor'));
|
||||
const syncUiState = () => saveButton.disabled = comboMarkdownEditor.isUploading();
|
||||
comboMarkdownEditor.container.addEventListener(ComboMarkdownEditor.EventUploadStateChanged, syncUiState);
|
||||
editContentZone.querySelector('.ui.cancel.button').addEventListener('click', cancelAndReset);
|
||||
editContentZone.querySelector('.ui.primary.button').addEventListener('click', saveAndRefresh);
|
||||
saveButton.addEventListener('click', saveAndRefresh);
|
||||
}
|
||||
|
||||
// Show write/preview tab and copy raw content as needed
|
||||
@ -93,6 +97,7 @@ async function onEditContent(event) {
|
||||
}
|
||||
comboMarkdownEditor.switchTabToEditor();
|
||||
comboMarkdownEditor.focus();
|
||||
triggerUploadStateChanged(comboMarkdownEditor.container);
|
||||
}
|
||||
|
||||
export function initRepoIssueCommentEdit() {
|
||||
|
@ -3,7 +3,7 @@ import {htmlEscape} from 'escape-goat';
|
||||
import {createTippy, showTemporaryTooltip} from '../modules/tippy.ts';
|
||||
import {hideElem, showElem, toggleElem} from '../utils/dom.ts';
|
||||
import {setFileFolding} from './file-fold.ts';
|
||||
import {getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
||||
import {ComboMarkdownEditor, getComboMarkdownEditor, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
||||
import {toAbsoluteUrl} from '../utils.ts';
|
||||
import {GET, POST} from '../modules/fetch.ts';
|
||||
import {showErrorToast} from '../modules/toast.ts';
|
||||
@ -483,9 +483,9 @@ export function initRepoPullRequestReview() {
|
||||
await handleReply(this);
|
||||
});
|
||||
|
||||
const $reviewBox = $('.review-box-panel');
|
||||
if ($reviewBox.length === 1) {
|
||||
const _promise = initComboMarkdownEditor($reviewBox.find('.combo-markdown-editor'));
|
||||
const elReviewBox = document.querySelector('.review-box-panel');
|
||||
if (elReviewBox) {
|
||||
initComboMarkdownEditor(elReviewBox.querySelector('.combo-markdown-editor'));
|
||||
}
|
||||
|
||||
// The following part is only for diff views
|
||||
@ -548,7 +548,7 @@ export function initRepoPullRequestReview() {
|
||||
$td.find("input[name='line']").val(idx);
|
||||
$td.find("input[name='side']").val(side === 'left' ? 'previous' : 'proposed');
|
||||
$td.find("input[name='path']").val(path);
|
||||
const editor = await initComboMarkdownEditor($td.find('.combo-markdown-editor'));
|
||||
const editor = await initComboMarkdownEditor($td[0].querySelector('.combo-markdown-editor'));
|
||||
editor.focus();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@ -669,20 +669,22 @@ export async function initSingleCommentEditor($commentForm) {
|
||||
// pages:
|
||||
// * normal new issue/pr page: no status-button, no comment-button (there is only a normal submit button which can submit empty content)
|
||||
// * issue/pr view page: with comment form, has status-button and comment-button
|
||||
const opts = {};
|
||||
const statusButton = document.querySelector('#status-button');
|
||||
const commentButton = document.querySelector('#comment-button');
|
||||
opts.onContentChanged = (editor) => {
|
||||
const editorText = editor.value().trim();
|
||||
const editor = await initComboMarkdownEditor($commentForm[0].querySelector('.combo-markdown-editor'));
|
||||
const statusButton = document.querySelector<HTMLButtonElement>('#status-button');
|
||||
const commentButton = document.querySelector<HTMLButtonElement>('#comment-button');
|
||||
const syncUiState = () => {
|
||||
const editorText = editor.value().trim(), isUploading = editor.isUploading();
|
||||
if (statusButton) {
|
||||
statusButton.textContent = statusButton.getAttribute(editorText ? 'data-status-and-comment' : 'data-status');
|
||||
statusButton.disabled = isUploading;
|
||||
}
|
||||
if (commentButton) {
|
||||
commentButton.disabled = !editorText;
|
||||
commentButton.disabled = !editorText || isUploading;
|
||||
}
|
||||
};
|
||||
const editor = await initComboMarkdownEditor($commentForm.find('.combo-markdown-editor'), opts);
|
||||
opts.onContentChanged(editor); // sync state of buttons with the initial content
|
||||
editor.container.addEventListener(ComboMarkdownEditor.EventUploadStateChanged, syncUiState);
|
||||
editor.container.addEventListener(ComboMarkdownEditor.EventEditorContentChanged, syncUiState);
|
||||
syncUiState();
|
||||
}
|
||||
|
||||
export function initIssueTemplateCommentEditors($commentForm) {
|
||||
@ -690,16 +692,13 @@ export function initIssueTemplateCommentEditors($commentForm) {
|
||||
// * new issue with issue template
|
||||
const $comboFields = $commentForm.find('.combo-editor-dropzone');
|
||||
|
||||
const initCombo = async ($combo) => {
|
||||
const $dropzoneContainer = $combo.find('.form-field-dropzone');
|
||||
const $formField = $combo.find('.form-field-real');
|
||||
const $markdownEditor = $combo.find('.combo-markdown-editor');
|
||||
const initCombo = async (elCombo) => {
|
||||
const $formField = $(elCombo.querySelector('.form-field-real'));
|
||||
const dropzoneContainer = elCombo.querySelector('.form-field-dropzone');
|
||||
const markdownEditor = elCombo.querySelector('.combo-markdown-editor');
|
||||
|
||||
const editor = await initComboMarkdownEditor($markdownEditor, {
|
||||
onContentChanged: (editor) => {
|
||||
$formField.val(editor.value());
|
||||
},
|
||||
});
|
||||
const editor = await initComboMarkdownEditor(markdownEditor);
|
||||
editor.container.addEventListener(ComboMarkdownEditor.EventEditorContentChanged, () => $formField.val(editor.value()));
|
||||
|
||||
$formField.on('focus', async () => {
|
||||
// deactivate all markdown editors
|
||||
@ -709,8 +708,8 @@ export function initIssueTemplateCommentEditors($commentForm) {
|
||||
|
||||
// activate this markdown editor
|
||||
hideElem($formField);
|
||||
showElem($markdownEditor);
|
||||
showElem($dropzoneContainer);
|
||||
showElem(markdownEditor);
|
||||
showElem(dropzoneContainer);
|
||||
|
||||
await editor.switchToUserPreference();
|
||||
editor.focus();
|
||||
@ -718,7 +717,7 @@ export function initIssueTemplateCommentEditors($commentForm) {
|
||||
};
|
||||
|
||||
for (const el of $comboFields) {
|
||||
initCombo($(el));
|
||||
initCombo(el);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ function initTagNameEditor() {
|
||||
}
|
||||
|
||||
function initRepoReleaseEditor() {
|
||||
const editor = document.querySelector('.repository.new.release .combo-markdown-editor');
|
||||
const editor = document.querySelector<HTMLElement>('.repository.new.release .combo-markdown-editor');
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
@ -4,11 +4,11 @@ import {fomanticMobileScreen} from '../modules/fomantic.ts';
|
||||
import {POST} from '../modules/fetch.ts';
|
||||
|
||||
async function initRepoWikiFormEditor() {
|
||||
const editArea = document.querySelector('.repository.wiki .combo-markdown-editor textarea');
|
||||
const editArea = document.querySelector<HTMLTextAreaElement>('.repository.wiki .combo-markdown-editor textarea');
|
||||
if (!editArea) return;
|
||||
|
||||
const form = document.querySelector('.repository.wiki.new .ui.form');
|
||||
const editorContainer = form.querySelector('.combo-markdown-editor');
|
||||
const editorContainer = form.querySelector<HTMLElement>('.combo-markdown-editor');
|
||||
let editor;
|
||||
|
||||
let renderRequesting = false;
|
||||
|
Loading…
Reference in New Issue
Block a user