mirror of
https://github.com/go-gitea/gitea.git
synced 2025-05-18 00:49:09 -04:00
Merge branch 'main' into support-folder-open-state
This commit is contained in:
commit
0788085649
24
.github/workflows/release-nightly.yml
vendored
24
.github/workflows/release-nightly.yml
vendored
@ -59,6 +59,8 @@ jobs:
|
|||||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
||||||
nightly-docker-rootful:
|
nightly-docker-rootful:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
|
permissions:
|
||||||
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||||
@ -85,6 +87,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Login to GHCR using PAT
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: fetch go modules
|
- name: fetch go modules
|
||||||
run: make vendor
|
run: make vendor
|
||||||
- name: build rootful docker image
|
- name: build rootful docker image
|
||||||
@ -93,9 +101,13 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
tags: |-
|
||||||
|
gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
||||||
|
ghcr.io/go-gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
||||||
nightly-docker-rootless:
|
nightly-docker-rootless:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
|
permissions:
|
||||||
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||||
@ -122,6 +134,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Login to GHCR using PAT
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: fetch go modules
|
- name: fetch go modules
|
||||||
run: make vendor
|
run: make vendor
|
||||||
- name: build rootless docker image
|
- name: build rootless docker image
|
||||||
@ -131,4 +149,6 @@ jobs:
|
|||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
file: Dockerfile.rootless
|
file: Dockerfile.rootless
|
||||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
tags: |-
|
||||||
|
gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
||||||
|
ghcr.io/go-gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
||||||
|
24
.github/workflows/release-tag-rc.yml
vendored
24
.github/workflows/release-tag-rc.yml
vendored
@ -69,6 +69,8 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
docker-rootful:
|
docker-rootful:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
|
permissions:
|
||||||
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||||
@ -79,7 +81,9 @@ jobs:
|
|||||||
- uses: docker/metadata-action@v5
|
- uses: docker/metadata-action@v5
|
||||||
id: meta
|
id: meta
|
||||||
with:
|
with:
|
||||||
images: gitea/gitea
|
images: |-
|
||||||
|
gitea/gitea
|
||||||
|
ghcr.io/go-gitea/gitea
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=false
|
latest=false
|
||||||
# 1.2.3-rc0
|
# 1.2.3-rc0
|
||||||
@ -90,6 +94,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Login to GHCR using PAT
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: build rootful docker image
|
- name: build rootful docker image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
@ -100,6 +110,8 @@ jobs:
|
|||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
docker-rootless:
|
docker-rootless:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
|
permissions:
|
||||||
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||||
@ -110,7 +122,9 @@ jobs:
|
|||||||
- uses: docker/metadata-action@v5
|
- uses: docker/metadata-action@v5
|
||||||
id: meta
|
id: meta
|
||||||
with:
|
with:
|
||||||
images: gitea/gitea
|
images: |-
|
||||||
|
gitea/gitea
|
||||||
|
ghcr.io/go-gitea/gitea
|
||||||
# each tag below will have the suffix of -rootless
|
# each tag below will have the suffix of -rootless
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=false
|
latest=false
|
||||||
@ -123,6 +137,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Login to GHCR using PAT
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: build rootless docker image
|
- name: build rootless docker image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
|
24
.github/workflows/release-tag-version.yml
vendored
24
.github/workflows/release-tag-version.yml
vendored
@ -14,6 +14,8 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
binary:
|
binary:
|
||||||
runs-on: namespace-profile-gitea-release-binary
|
runs-on: namespace-profile-gitea-release-binary
|
||||||
|
permissions:
|
||||||
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||||
@ -71,6 +73,8 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
docker-rootful:
|
docker-rootful:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
|
permissions:
|
||||||
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||||
@ -81,7 +85,9 @@ jobs:
|
|||||||
- uses: docker/metadata-action@v5
|
- uses: docker/metadata-action@v5
|
||||||
id: meta
|
id: meta
|
||||||
with:
|
with:
|
||||||
images: gitea/gitea
|
images: |-
|
||||||
|
gitea/gitea
|
||||||
|
ghcr.io/go-gitea/gitea
|
||||||
# this will generate tags in the following format:
|
# this will generate tags in the following format:
|
||||||
# latest
|
# latest
|
||||||
# 1
|
# 1
|
||||||
@ -96,6 +102,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Login to GHCR using PAT
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: build rootful docker image
|
- name: build rootful docker image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
@ -116,7 +128,9 @@ jobs:
|
|||||||
- uses: docker/metadata-action@v5
|
- uses: docker/metadata-action@v5
|
||||||
id: meta
|
id: meta
|
||||||
with:
|
with:
|
||||||
images: gitea/gitea
|
images: |-
|
||||||
|
gitea/gitea
|
||||||
|
ghcr.io/go-gitea/gitea
|
||||||
# each tag below will have the suffix of -rootless
|
# each tag below will have the suffix of -rootless
|
||||||
flavor: |
|
flavor: |
|
||||||
suffix=-rootless,onlatest=true
|
suffix=-rootless,onlatest=true
|
||||||
@ -134,6 +148,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Login to GHCR using PAT
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: build rootless docker image
|
- name: build rootless docker image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ScopeSortPrefix = "scope-"
|
||||||
|
|
||||||
// IssuesOptions represents options of an issue.
|
// IssuesOptions represents options of an issue.
|
||||||
type IssuesOptions struct { //nolint
|
type IssuesOptions struct { //nolint
|
||||||
Paginator *db.ListOptions
|
Paginator *db.ListOptions
|
||||||
@ -70,6 +72,17 @@ func (o *IssuesOptions) Copy(edit ...func(options *IssuesOptions)) *IssuesOption
|
|||||||
// applySorts sort an issues-related session based on the provided
|
// applySorts sort an issues-related session based on the provided
|
||||||
// sortType string
|
// sortType string
|
||||||
func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) {
|
func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) {
|
||||||
|
// Since this sortType is dynamically created, it has to be treated specially.
|
||||||
|
if strings.HasPrefix(sortType, ScopeSortPrefix) {
|
||||||
|
scope := strings.TrimPrefix(sortType, ScopeSortPrefix)
|
||||||
|
sess.Join("LEFT", "issue_label", "issue.id = issue_label.issue_id")
|
||||||
|
// "exclusive_order=0" means "no order is set", so exclude it from the JOIN criteria and then "LEFT JOIN" result is also null
|
||||||
|
sess.Join("LEFT", "label", "label.id = issue_label.label_id AND label.exclusive_order <> 0 AND label.name LIKE ?", scope+"/%")
|
||||||
|
// Use COALESCE to make sure we sort NULL last regardless of backend DB (2147483647 == max int)
|
||||||
|
sess.OrderBy("COALESCE(label.exclusive_order, 2147483647) ASC").Desc("issue.id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch sortType {
|
switch sortType {
|
||||||
case "oldest":
|
case "oldest":
|
||||||
sess.Asc("issue.created_unix").Asc("issue.id")
|
sess.Asc("issue.created_unix").Asc("issue.id")
|
||||||
|
@ -87,6 +87,7 @@ type Label struct {
|
|||||||
OrgID int64 `xorm:"INDEX"`
|
OrgID int64 `xorm:"INDEX"`
|
||||||
Name string
|
Name string
|
||||||
Exclusive bool
|
Exclusive bool
|
||||||
|
ExclusiveOrder int `xorm:"DEFAULT 0"` // 0 means no exclusive order
|
||||||
Description string
|
Description string
|
||||||
Color string `xorm:"VARCHAR(7)"`
|
Color string `xorm:"VARCHAR(7)"`
|
||||||
NumIssues int
|
NumIssues int
|
||||||
@ -236,7 +237,7 @@ func UpdateLabel(ctx context.Context, l *Label) error {
|
|||||||
}
|
}
|
||||||
l.Color = color
|
l.Color = color
|
||||||
|
|
||||||
return updateLabelCols(ctx, l, "name", "description", "color", "exclusive", "archived_unix")
|
return updateLabelCols(ctx, l, "name", "description", "color", "exclusive", "exclusive_order", "archived_unix")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteLabel delete a label
|
// DeleteLabel delete a label
|
||||||
|
@ -380,6 +380,7 @@ func prepareMigrationTasks() []*migration {
|
|||||||
newMigration(316, "Add description for secrets and variables", v1_24.AddDescriptionForSecretsAndVariables),
|
newMigration(316, "Add description for secrets and variables", v1_24.AddDescriptionForSecretsAndVariables),
|
||||||
newMigration(317, "Add new index for action for heatmap", v1_24.AddNewIndexForUserDashboard),
|
newMigration(317, "Add new index for action for heatmap", v1_24.AddNewIndexForUserDashboard),
|
||||||
newMigration(318, "Add anonymous_access_mode for repo_unit", v1_24.AddRepoUnitAnonymousAccessMode),
|
newMigration(318, "Add anonymous_access_mode for repo_unit", v1_24.AddRepoUnitAnonymousAccessMode),
|
||||||
|
newMigration(319, "Add ExclusiveOrder to Label table", v1_24.AddExclusiveOrderColumnToLabelTable),
|
||||||
}
|
}
|
||||||
return preparedMigrations
|
return preparedMigrations
|
||||||
}
|
}
|
||||||
|
16
models/migrations/v1_24/v319.go
Normal file
16
models/migrations/v1_24/v319.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v1_24 //nolint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AddExclusiveOrderColumnToLabelTable(x *xorm.Engine) error {
|
||||||
|
type Label struct {
|
||||||
|
ExclusiveOrder int `xorm:"DEFAULT 0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.Sync(new(Label))
|
||||||
|
}
|
@ -6,6 +6,7 @@ package db
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
issue_model "code.gitea.io/gitea/models/issues"
|
issue_model "code.gitea.io/gitea/models/issues"
|
||||||
@ -18,7 +19,7 @@ import (
|
|||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ internal.Indexer = &Indexer{}
|
var _ internal.Indexer = (*Indexer)(nil)
|
||||||
|
|
||||||
// Indexer implements Indexer interface to use database's like search
|
// Indexer implements Indexer interface to use database's like search
|
||||||
type Indexer struct {
|
type Indexer struct {
|
||||||
@ -29,11 +30,9 @@ func (i *Indexer) SupportedSearchModes() []indexer.SearchMode {
|
|||||||
return indexer.SearchModesExactWords()
|
return indexer.SearchModesExactWords()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIndexer() *Indexer {
|
var GetIndexer = sync.OnceValue(func() *Indexer {
|
||||||
return &Indexer{
|
return &Indexer{Indexer: &inner_db.Indexer{}}
|
||||||
Indexer: &inner_db.Indexer{},
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Index dummy function
|
// Index dummy function
|
||||||
func (i *Indexer) Index(_ context.Context, _ ...*internal.IndexerData) error {
|
func (i *Indexer) Index(_ context.Context, _ ...*internal.IndexerData) error {
|
||||||
@ -122,7 +121,11 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ids, total, err := issue_model.IssueIDs(ctx, opt, cond)
|
return i.FindWithIssueOptions(ctx, opt, cond)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Indexer) FindWithIssueOptions(ctx context.Context, opt *issue_model.IssuesOptions, otherConds ...builder.Cond) (*internal.SearchResult, error) {
|
||||||
|
ids, total, err := issue_model.IssueIDs(ctx, opt, otherConds...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package db
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
issue_model "code.gitea.io/gitea/models/issues"
|
issue_model "code.gitea.io/gitea/models/issues"
|
||||||
@ -34,7 +35,11 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
|
|||||||
case internal.SortByDeadlineAsc:
|
case internal.SortByDeadlineAsc:
|
||||||
sortType = "nearduedate"
|
sortType = "nearduedate"
|
||||||
default:
|
default:
|
||||||
sortType = "newest"
|
if strings.HasPrefix(string(options.SortBy), issue_model.ScopeSortPrefix) {
|
||||||
|
sortType = string(options.SortBy)
|
||||||
|
} else {
|
||||||
|
sortType = "newest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See the comment of issues_model.SearchOptions for the reason why we need to convert
|
// See the comment of issues_model.SearchOptions for the reason why we need to convert
|
||||||
@ -68,7 +73,6 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
|
|||||||
ExcludedLabelNames: nil,
|
ExcludedLabelNames: nil,
|
||||||
IncludeMilestones: nil,
|
IncludeMilestones: nil,
|
||||||
SortType: sortType,
|
SortType: sortType,
|
||||||
IssueIDs: nil,
|
|
||||||
UpdatedAfterUnix: options.UpdatedAfterUnix.Value(),
|
UpdatedAfterUnix: options.UpdatedAfterUnix.Value(),
|
||||||
UpdatedBeforeUnix: options.UpdatedBeforeUnix.Value(),
|
UpdatedBeforeUnix: options.UpdatedBeforeUnix.Value(),
|
||||||
PriorityRepoID: 0,
|
PriorityRepoID: 0,
|
||||||
|
@ -4,12 +4,19 @@
|
|||||||
package issues
|
package issues
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
|
"code.gitea.io/gitea/modules/indexer/issues/internal"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOptions {
|
func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOptions {
|
||||||
|
if opts.IssueIDs != nil {
|
||||||
|
setting.PanicInDevOrTesting("Indexer SearchOptions doesn't support IssueIDs")
|
||||||
|
}
|
||||||
searchOpt := &SearchOptions{
|
searchOpt := &SearchOptions{
|
||||||
Keyword: keyword,
|
Keyword: keyword,
|
||||||
RepoIDs: opts.RepoIDs,
|
RepoIDs: opts.RepoIDs,
|
||||||
@ -95,7 +102,11 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
|
|||||||
// Unsupported sort type for search
|
// Unsupported sort type for search
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
searchOpt.SortBy = SortByUpdatedDesc
|
if strings.HasPrefix(opts.SortType, issues_model.ScopeSortPrefix) {
|
||||||
|
searchOpt.SortBy = internal.SortBy(opts.SortType)
|
||||||
|
} else {
|
||||||
|
searchOpt.SortBy = SortByUpdatedDesc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return searchOpt
|
return searchOpt
|
||||||
|
@ -103,7 +103,7 @@ func InitIssueIndexer(syncReindex bool) {
|
|||||||
log.Fatal("Unable to issueIndexer.Init with connection %s Error: %v", setting.Indexer.IssueConnStr, err)
|
log.Fatal("Unable to issueIndexer.Init with connection %s Error: %v", setting.Indexer.IssueConnStr, err)
|
||||||
}
|
}
|
||||||
case "db":
|
case "db":
|
||||||
issueIndexer = db.NewIndexer()
|
issueIndexer = db.GetIndexer()
|
||||||
case "meilisearch":
|
case "meilisearch":
|
||||||
issueIndexer = meilisearch.NewIndexer(setting.Indexer.IssueConnStr, setting.Indexer.IssueConnAuth, setting.Indexer.IssueIndexerName)
|
issueIndexer = meilisearch.NewIndexer(setting.Indexer.IssueConnStr, setting.Indexer.IssueConnAuth, setting.Indexer.IssueIndexerName)
|
||||||
existed, err = issueIndexer.Init(ctx)
|
existed, err = issueIndexer.Init(ctx)
|
||||||
@ -291,19 +291,22 @@ func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, err
|
|||||||
// So if the user creates an issue and list issues immediately, the issue may not be listed because the indexer needs time to index the issue.
|
// So if the user creates an issue and list issues immediately, the issue may not be listed because the indexer needs time to index the issue.
|
||||||
// Even worse, the external indexer like elastic search may not be available for a while,
|
// Even worse, the external indexer like elastic search may not be available for a while,
|
||||||
// and the user may not be able to list issues completely until it is available again.
|
// and the user may not be able to list issues completely until it is available again.
|
||||||
ix = db.NewIndexer()
|
ix = db.GetIndexer()
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := ix.Search(ctx, opts)
|
result, err := ix.Search(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
return SearchResultToIDSlice(result), result.Total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchResultToIDSlice(result *internal.SearchResult) []int64 {
|
||||||
ret := make([]int64, 0, len(result.Hits))
|
ret := make([]int64, 0, len(result.Hits))
|
||||||
for _, hit := range result.Hits {
|
for _, hit := range result.Hits {
|
||||||
ret = append(ret, hit.ID)
|
ret = append(ret, hit.ID)
|
||||||
}
|
}
|
||||||
|
return ret
|
||||||
return ret, result.Total, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountIssues counts issues by options. It is a shortcut of SearchIssues(ctx, opts) but only returns the total count.
|
// CountIssues counts issues by options. It is a shortcut of SearchIssues(ctx, opts) but only returns the total count.
|
||||||
|
@ -14,10 +14,11 @@ var colorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$")
|
|||||||
|
|
||||||
// Label represents label information loaded from template
|
// Label represents label information loaded from template
|
||||||
type Label struct {
|
type Label struct {
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
Color string `yaml:"color"`
|
Color string `yaml:"color"`
|
||||||
Description string `yaml:"description,omitempty"`
|
Description string `yaml:"description,omitempty"`
|
||||||
Exclusive bool `yaml:"exclusive,omitempty"`
|
Exclusive bool `yaml:"exclusive,omitempty"`
|
||||||
|
ExclusiveOrder int `yaml:"exclusive_order,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormalizeColor normalizes a color string to a 6-character hex code
|
// NormalizeColor normalizes a color string to a 6-character hex code
|
||||||
|
@ -127,10 +127,11 @@ func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg
|
|||||||
labels := make([]*issues_model.Label, len(list))
|
labels := make([]*issues_model.Label, len(list))
|
||||||
for i := 0; i < len(list); i++ {
|
for i := 0; i < len(list); i++ {
|
||||||
labels[i] = &issues_model.Label{
|
labels[i] = &issues_model.Label{
|
||||||
Name: list[i].Name,
|
Name: list[i].Name,
|
||||||
Exclusive: list[i].Exclusive,
|
Exclusive: list[i].Exclusive,
|
||||||
Description: list[i].Description,
|
ExclusiveOrder: list[i].ExclusiveOrder,
|
||||||
Color: list[i].Color,
|
Description: list[i].Description,
|
||||||
|
Color: list[i].Color,
|
||||||
}
|
}
|
||||||
if isOrg {
|
if isOrg {
|
||||||
labels[i].OrgID = id
|
labels[i].OrgID = id
|
||||||
|
@ -170,13 +170,28 @@ func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML {
|
|||||||
itemColor := "#" + hex.EncodeToString(itemBytes)
|
itemColor := "#" + hex.EncodeToString(itemBytes)
|
||||||
scopeColor := "#" + hex.EncodeToString(scopeBytes)
|
scopeColor := "#" + hex.EncodeToString(scopeBytes)
|
||||||
|
|
||||||
|
if label.ExclusiveOrder > 0 {
|
||||||
|
// <scope> | <label> | <order>
|
||||||
|
return htmlutil.HTMLFormat(`<span class="ui label %s scope-parent" data-tooltip-content title="%s">`+
|
||||||
|
`<div class="ui label scope-left" style="color: %s !important; background-color: %s !important">%s</div>`+
|
||||||
|
`<div class="ui label scope-middle" style="color: %s !important; background-color: %s !important">%s</div>`+
|
||||||
|
`<div class="ui label scope-right">%d</div>`+
|
||||||
|
`</span>`,
|
||||||
|
extraCSSClasses, descriptionText,
|
||||||
|
textColor, scopeColor, scopeHTML,
|
||||||
|
textColor, itemColor, itemHTML,
|
||||||
|
label.ExclusiveOrder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// <scope> | <label>
|
||||||
return htmlutil.HTMLFormat(`<span class="ui label %s scope-parent" data-tooltip-content title="%s">`+
|
return htmlutil.HTMLFormat(`<span class="ui label %s scope-parent" data-tooltip-content title="%s">`+
|
||||||
`<div class="ui label scope-left" style="color: %s !important; background-color: %s !important">%s</div>`+
|
`<div class="ui label scope-left" style="color: %s !important; background-color: %s !important">%s</div>`+
|
||||||
`<div class="ui label scope-right" style="color: %s !important; background-color: %s !important">%s</div>`+
|
`<div class="ui label scope-right" style="color: %s !important; background-color: %s !important">%s</div>`+
|
||||||
`</span>`,
|
`</span>`,
|
||||||
extraCSSClasses, descriptionText,
|
extraCSSClasses, descriptionText,
|
||||||
textColor, scopeColor, scopeHTML,
|
textColor, scopeColor, scopeHTML,
|
||||||
textColor, itemColor, itemHTML)
|
textColor, itemColor, itemHTML,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderEmoji renders html text with emoji post processors
|
// RenderEmoji renders html text with emoji post processors
|
||||||
|
@ -22,49 +22,60 @@ labels:
|
|||||||
description: Breaking change that won't be backward compatible
|
description: Breaking change that won't be backward compatible
|
||||||
- name: "Reviewed/Duplicate"
|
- name: "Reviewed/Duplicate"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 2
|
||||||
color: 616161
|
color: 616161
|
||||||
description: This issue or pull request already exists
|
description: This issue or pull request already exists
|
||||||
- name: "Reviewed/Invalid"
|
- name: "Reviewed/Invalid"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 3
|
||||||
color: 546e7a
|
color: 546e7a
|
||||||
description: Invalid issue
|
description: Invalid issue
|
||||||
- name: "Reviewed/Confirmed"
|
- name: "Reviewed/Confirmed"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 1
|
||||||
color: 795548
|
color: 795548
|
||||||
description: Issue has been confirmed
|
description: Issue has been confirmed
|
||||||
- name: "Reviewed/Won't Fix"
|
- name: "Reviewed/Won't Fix"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 3
|
||||||
color: eeeeee
|
color: eeeeee
|
||||||
description: This issue won't be fixed
|
description: This issue won't be fixed
|
||||||
- name: "Status/Need More Info"
|
- name: "Status/Need More Info"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 2
|
||||||
color: 424242
|
color: 424242
|
||||||
description: Feedback is required to reproduce issue or to continue work
|
description: Feedback is required to reproduce issue or to continue work
|
||||||
- name: "Status/Blocked"
|
- name: "Status/Blocked"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 1
|
||||||
color: 880e4f
|
color: 880e4f
|
||||||
description: Something is blocking this issue or pull request
|
description: Something is blocking this issue or pull request
|
||||||
- name: "Status/Abandoned"
|
- name: "Status/Abandoned"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 3
|
||||||
color: "222222"
|
color: "222222"
|
||||||
description: Somebody has started to work on this but abandoned work
|
description: Somebody has started to work on this but abandoned work
|
||||||
- name: "Priority/Critical"
|
- name: "Priority/Critical"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 1
|
||||||
color: b71c1c
|
color: b71c1c
|
||||||
description: The priority is critical
|
description: The priority is critical
|
||||||
priority: critical
|
priority: critical
|
||||||
- name: "Priority/High"
|
- name: "Priority/High"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 2
|
||||||
color: d32f2f
|
color: d32f2f
|
||||||
description: The priority is high
|
description: The priority is high
|
||||||
priority: high
|
priority: high
|
||||||
- name: "Priority/Medium"
|
- name: "Priority/Medium"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 3
|
||||||
color: e64a19
|
color: e64a19
|
||||||
description: The priority is medium
|
description: The priority is medium
|
||||||
priority: medium
|
priority: medium
|
||||||
- name: "Priority/Low"
|
- name: "Priority/Low"
|
||||||
exclusive: true
|
exclusive: true
|
||||||
|
exclusive_order: 4
|
||||||
color: 4caf50
|
color: 4caf50
|
||||||
description: The priority is low
|
description: The priority is low
|
||||||
priority: low
|
priority: low
|
||||||
|
@ -1655,6 +1655,8 @@ issues.label_archived_filter = Show archived labels
|
|||||||
issues.label_archive_tooltip = Archived labels are excluded by default from the suggestions when searching by label.
|
issues.label_archive_tooltip = Archived labels are excluded by default from the suggestions when searching by label.
|
||||||
issues.label_exclusive_desc = Name the label <code>scope/item</code> to make it mutually exclusive with other <code>scope/</code> labels.
|
issues.label_exclusive_desc = Name the label <code>scope/item</code> to make it mutually exclusive with other <code>scope/</code> labels.
|
||||||
issues.label_exclusive_warning = Any conflicting scoped labels will be removed when editing the labels of an issue or pull request.
|
issues.label_exclusive_warning = Any conflicting scoped labels will be removed when editing the labels of an issue or pull request.
|
||||||
|
issues.label_exclusive_order = Sort Order
|
||||||
|
issues.label_exclusive_order_tooltip = Exclusive labels in the same scope will be sorted according to this numeric order.
|
||||||
issues.label_count = %d labels
|
issues.label_count = %d labels
|
||||||
issues.label_open_issues = %d open issues/pull requests
|
issues.label_open_issues = %d open issues/pull requests
|
||||||
issues.label_edit = Edit
|
issues.label_edit = Edit
|
||||||
|
@ -113,6 +113,7 @@ copy_type_unsupported=无法复制此类型的文件内容
|
|||||||
write=撰写
|
write=撰写
|
||||||
preview=预览
|
preview=预览
|
||||||
loading=正在加载...
|
loading=正在加载...
|
||||||
|
files=文件
|
||||||
|
|
||||||
error=错误
|
error=错误
|
||||||
error404=您正尝试访问的页面 <strong>不存在</strong> 或 <strong>您尚未被授权</strong> 查看该页面。
|
error404=您正尝试访问的页面 <strong>不存在</strong> 或 <strong>您尚未被授权</strong> 查看该页面。
|
||||||
@ -169,6 +170,10 @@ search=搜索...
|
|||||||
type_tooltip=搜索类型
|
type_tooltip=搜索类型
|
||||||
fuzzy=模糊
|
fuzzy=模糊
|
||||||
fuzzy_tooltip=包含近似匹配搜索词的结果
|
fuzzy_tooltip=包含近似匹配搜索词的结果
|
||||||
|
words=词
|
||||||
|
words_tooltip=仅包含匹配搜索词的结果
|
||||||
|
regexp=正则表达式
|
||||||
|
regexp_tooltip=仅包含匹配正则表达式搜索词的结果
|
||||||
exact=精确
|
exact=精确
|
||||||
exact_tooltip=仅包含精确匹配搜索词的结果
|
exact_tooltip=仅包含精确匹配搜索词的结果
|
||||||
repo_kind=搜索仓库...
|
repo_kind=搜索仓库...
|
||||||
@ -385,6 +390,12 @@ show_only_public=只显示公开的
|
|||||||
|
|
||||||
issues.in_your_repos=在您的仓库中
|
issues.in_your_repos=在您的仓库中
|
||||||
|
|
||||||
|
guide_title=无活动
|
||||||
|
guide_desc=您目前没有关注任何仓库或用户,所以没有要显示的内容。 您可以从下面的链接中探索感兴趣的仓库或用户。
|
||||||
|
explore_repos=探索仓库
|
||||||
|
explore_users=探索用户
|
||||||
|
empty_org=目前还没有组织。
|
||||||
|
empty_repo=目前还没有仓库。
|
||||||
|
|
||||||
[explore]
|
[explore]
|
||||||
repos=仓库
|
repos=仓库
|
||||||
@ -446,6 +457,7 @@ oauth_signup_submit=完成账号
|
|||||||
oauth_signin_tab=绑定到现有帐号
|
oauth_signin_tab=绑定到现有帐号
|
||||||
oauth_signin_title=登录以授权绑定帐户
|
oauth_signin_title=登录以授权绑定帐户
|
||||||
oauth_signin_submit=绑定账号
|
oauth_signin_submit=绑定账号
|
||||||
|
oauth.signin.error.general=处理授权请求时出错:%s。如果此错误仍然存在,请与站点管理员联系。
|
||||||
oauth.signin.error.access_denied=授权请求被拒绝。
|
oauth.signin.error.access_denied=授权请求被拒绝。
|
||||||
oauth.signin.error.temporarily_unavailable=授权失败,因为认证服务器暂时不可用。请稍后再试。
|
oauth.signin.error.temporarily_unavailable=授权失败,因为认证服务器暂时不可用。请稍后再试。
|
||||||
oauth_callback_unable_auto_reg=自动注册已启用,但OAuth2 提供商 %[1]s 返回缺失的字段:%[2]s,无法自动创建帐户,请创建或链接到一个帐户,或联系站点管理员。
|
oauth_callback_unable_auto_reg=自动注册已启用,但OAuth2 提供商 %[1]s 返回缺失的字段:%[2]s,无法自动创建帐户,请创建或链接到一个帐户,或联系站点管理员。
|
||||||
@ -718,6 +730,8 @@ public_profile=公开信息
|
|||||||
biography_placeholder=告诉我们一点您自己! (您可以使用Markdown)
|
biography_placeholder=告诉我们一点您自己! (您可以使用Markdown)
|
||||||
location_placeholder=与他人分享你的大概位置
|
location_placeholder=与他人分享你的大概位置
|
||||||
profile_desc=控制您的个人资料对其他用户的显示方式。您的主要电子邮件地址将用于通知、密码恢复和基于网页界面的 Git 操作
|
profile_desc=控制您的个人资料对其他用户的显示方式。您的主要电子邮件地址将用于通知、密码恢复和基于网页界面的 Git 操作
|
||||||
|
password_username_disabled=您不被允许更改你的用户名。更多详情请联系您的系统管理员。
|
||||||
|
password_full_name_disabled=您不被允许更改你的全名。请联系您的站点管理员了解更多详情。
|
||||||
full_name=自定义名称
|
full_name=自定义名称
|
||||||
website=个人网站
|
website=个人网站
|
||||||
location=所在地区
|
location=所在地区
|
||||||
@ -912,6 +926,7 @@ permission_not_set=未设置
|
|||||||
permission_no_access=无访问权限
|
permission_no_access=无访问权限
|
||||||
permission_read=可读
|
permission_read=可读
|
||||||
permission_write=读写
|
permission_write=读写
|
||||||
|
permission_anonymous_read=匿名读
|
||||||
access_token_desc=所选令牌权限仅限于对应的 <a %s>API</a> 路由的授权。阅读 <a %s>文档</a> 以获取更多信息。
|
access_token_desc=所选令牌权限仅限于对应的 <a %s>API</a> 路由的授权。阅读 <a %s>文档</a> 以获取更多信息。
|
||||||
at_least_one_permission=你需要选择至少一个权限才能创建令牌
|
at_least_one_permission=你需要选择至少一个权限才能创建令牌
|
||||||
permissions_list=权限:
|
permissions_list=权限:
|
||||||
@ -1014,6 +1029,9 @@ new_repo_helper=代码仓库包含了所有的项目文件,包括版本历史
|
|||||||
owner=拥有者
|
owner=拥有者
|
||||||
owner_helper=由于最大仓库数量限制,一些组织可能不会显示在下拉列表中。
|
owner_helper=由于最大仓库数量限制,一些组织可能不会显示在下拉列表中。
|
||||||
repo_name=仓库名称
|
repo_name=仓库名称
|
||||||
|
repo_name_profile_public_hint=.profile 是一个特殊的存储库,您可以使用它将 README.md 添加到您的公共组织资料中,任何人都可以看到。请确保它是公开的,并使用个人资料目录中的 README 对其进行初始化以开始使用。
|
||||||
|
repo_name_profile_private_hint=.profile-private 是一个特殊的存储库,您可以使用它向您的组织成员个人资料添加 README.md,仅对组织成员可见。请确保它是私有的,并使用个人资料目录中的 README 对其进行初始化以开始使用。
|
||||||
|
repo_name_helper=理想的仓库名称应由简短、有意义和独特的关键词组成。".profile" 和 ".profile-private" 可用于为用户/组织添加 README.md。
|
||||||
repo_size=仓库大小
|
repo_size=仓库大小
|
||||||
template=模板
|
template=模板
|
||||||
template_select=选择模板
|
template_select=选择模板
|
||||||
@ -1110,6 +1128,7 @@ blame.ignore_revs=忽略 <a href="%s">.git-blame-ignore-revs</a> 的修订。点
|
|||||||
blame.ignore_revs.failed=忽略 <a href="%s">.git-blame-ignore-revs</a> 版本失败。
|
blame.ignore_revs.failed=忽略 <a href="%s">.git-blame-ignore-revs</a> 版本失败。
|
||||||
user_search_tooltip=最多显示30名用户
|
user_search_tooltip=最多显示30名用户
|
||||||
|
|
||||||
|
tree_path_not_found=%[2]s 中不存在路径 %[1]s
|
||||||
|
|
||||||
transfer.accept=接受转移
|
transfer.accept=接受转移
|
||||||
transfer.accept_desc=`转移到 "%s"`
|
transfer.accept_desc=`转移到 "%s"`
|
||||||
@ -1120,6 +1139,7 @@ transfer.no_permission_to_reject=您没有权限拒绝此转让。
|
|||||||
|
|
||||||
desc.private=私有库
|
desc.private=私有库
|
||||||
desc.public=公开
|
desc.public=公开
|
||||||
|
desc.public_access=公开访问
|
||||||
desc.template=模板
|
desc.template=模板
|
||||||
desc.internal=内部
|
desc.internal=内部
|
||||||
desc.archived=已存档
|
desc.archived=已存档
|
||||||
@ -1227,6 +1247,7 @@ create_new_repo_command=从命令行创建一个新的仓库
|
|||||||
push_exist_repo=从命令行推送已经创建的仓库
|
push_exist_repo=从命令行推送已经创建的仓库
|
||||||
empty_message=这个家伙很懒,什么都没有推送。
|
empty_message=这个家伙很懒,什么都没有推送。
|
||||||
broken_message=无法读取此仓库下的 Git 数据。 联系此实例的管理员或删除此仓库。
|
broken_message=无法读取此仓库下的 Git 数据。 联系此实例的管理员或删除此仓库。
|
||||||
|
no_branch=该仓库没有任何分支。
|
||||||
|
|
||||||
code=代码
|
code=代码
|
||||||
code.desc=查看源码、文件、提交和分支。
|
code.desc=查看源码、文件、提交和分支。
|
||||||
@ -1339,6 +1360,8 @@ editor.new_branch_name_desc=新的分支名称...
|
|||||||
editor.cancel=取消
|
editor.cancel=取消
|
||||||
editor.filename_cannot_be_empty=文件名不能为空。
|
editor.filename_cannot_be_empty=文件名不能为空。
|
||||||
editor.filename_is_invalid=文件名 %s 无效
|
editor.filename_is_invalid=文件名 %s 无效
|
||||||
|
editor.commit_email=提交邮箱地址
|
||||||
|
editor.invalid_commit_email=提交的邮箱地址无效。
|
||||||
editor.branch_does_not_exist=此仓库中不存在名为 %s 的分支。
|
editor.branch_does_not_exist=此仓库中不存在名为 %s 的分支。
|
||||||
editor.branch_already_exists=此仓库已存在名为 %s 的分支。
|
editor.branch_already_exists=此仓库已存在名为 %s 的分支。
|
||||||
editor.directory_is_a_file=%s 已经作为文件名在此仓库中存在。
|
editor.directory_is_a_file=%s 已经作为文件名在此仓库中存在。
|
||||||
@ -1387,6 +1410,7 @@ commits.signed_by_untrusted_user_unmatched=由与提交者不匹配的未授信
|
|||||||
commits.gpg_key_id=GPG 密钥 ID
|
commits.gpg_key_id=GPG 密钥 ID
|
||||||
commits.ssh_key_fingerprint=SSH 密钥指纹
|
commits.ssh_key_fingerprint=SSH 密钥指纹
|
||||||
commits.view_path=在历史记录中的此处查看
|
commits.view_path=在历史记录中的此处查看
|
||||||
|
commits.view_file_diff=查看提交中的文件更改
|
||||||
|
|
||||||
commit.operations=操作
|
commit.operations=操作
|
||||||
commit.revert=还原
|
commit.revert=还原
|
||||||
@ -1398,7 +1422,7 @@ commit.cherry-pick-content=选择 cherry-pick 的目标分支:
|
|||||||
|
|
||||||
commitstatus.error=错误
|
commitstatus.error=错误
|
||||||
commitstatus.failure=失败
|
commitstatus.failure=失败
|
||||||
commitstatus.pending=待定
|
commitstatus.pending=队列
|
||||||
commitstatus.success=成功
|
commitstatus.success=成功
|
||||||
|
|
||||||
ext_issues=访问外部工单
|
ext_issues=访问外部工单
|
||||||
@ -1433,7 +1457,7 @@ projects.column.set_default=设为默认
|
|||||||
projects.column.set_default_desc=设置此列为未分类问题和合并请求的默认值
|
projects.column.set_default_desc=设置此列为未分类问题和合并请求的默认值
|
||||||
projects.column.delete=删除列
|
projects.column.delete=删除列
|
||||||
projects.column.deletion_desc=删除项目列会将所有相关问题移到“未分类”。是否继续?
|
projects.column.deletion_desc=删除项目列会将所有相关问题移到“未分类”。是否继续?
|
||||||
projects.column.color=彩色
|
projects.column.color=颜色
|
||||||
projects.open=开启
|
projects.open=开启
|
||||||
projects.close=关闭
|
projects.close=关闭
|
||||||
projects.column.assigned_to=指派给
|
projects.column.assigned_to=指派给
|
||||||
@ -1447,6 +1471,8 @@ issues.filter_milestones=筛选里程碑
|
|||||||
issues.filter_projects=筛选项目
|
issues.filter_projects=筛选项目
|
||||||
issues.filter_labels=筛选标签
|
issues.filter_labels=筛选标签
|
||||||
issues.filter_reviewers=筛选审核者
|
issues.filter_reviewers=筛选审核者
|
||||||
|
issues.filter_no_results=没有结果
|
||||||
|
issues.filter_no_results_placeholder=请尝试调整您的搜索过滤器。
|
||||||
issues.new=创建工单
|
issues.new=创建工单
|
||||||
issues.new.title_empty=标题不能为空
|
issues.new.title_empty=标题不能为空
|
||||||
issues.new.labels=标签
|
issues.new.labels=标签
|
||||||
@ -1520,8 +1546,10 @@ issues.filter_milestone_open=进行中的里程碑
|
|||||||
issues.filter_milestone_closed=已关闭的里程碑
|
issues.filter_milestone_closed=已关闭的里程碑
|
||||||
issues.filter_project=项目
|
issues.filter_project=项目
|
||||||
issues.filter_project_all=所有项目
|
issues.filter_project_all=所有项目
|
||||||
issues.filter_project_none=暂无项目
|
issues.filter_project_none=未加项目
|
||||||
issues.filter_assignee=指派人筛选
|
issues.filter_assignee=指派人筛选
|
||||||
|
issues.filter_assignee_no_assignee=未指派给任何人
|
||||||
|
issues.filter_assignee_any_assignee=已有指派
|
||||||
issues.filter_poster=作者
|
issues.filter_poster=作者
|
||||||
issues.filter_user_placeholder=搜索用户
|
issues.filter_user_placeholder=搜索用户
|
||||||
issues.filter_user_no_select=所有用户
|
issues.filter_user_no_select=所有用户
|
||||||
@ -1595,9 +1623,9 @@ issues.ref_reopened_from=`<a href="%[3]s">重新打开这个工单 %[4]s</a> <a
|
|||||||
issues.ref_from=`来自 %[1]s`
|
issues.ref_from=`来自 %[1]s`
|
||||||
issues.author=作者
|
issues.author=作者
|
||||||
issues.author_helper=此用户是作者。
|
issues.author_helper=此用户是作者。
|
||||||
issues.role.owner=管理员
|
issues.role.owner=所有者
|
||||||
issues.role.owner_helper=该用户是该仓库的所有者。
|
issues.role.owner_helper=该用户是该仓库的所有者。
|
||||||
issues.role.member=普通成员
|
issues.role.member=成员
|
||||||
issues.role.member_helper=该用户是拥有该仓库的组织成员。
|
issues.role.member_helper=该用户是拥有该仓库的组织成员。
|
||||||
issues.role.collaborator=协作者
|
issues.role.collaborator=协作者
|
||||||
issues.role.collaborator_helper=该用户已被邀请在仓库上进行协作。
|
issues.role.collaborator_helper=该用户已被邀请在仓库上进行协作。
|
||||||
@ -1676,11 +1704,13 @@ issues.timetracker_timer_manually_add=添加时间
|
|||||||
|
|
||||||
issues.time_estimate_set=设置预计时间
|
issues.time_estimate_set=设置预计时间
|
||||||
issues.time_estimate_display=预计: %s
|
issues.time_estimate_display=预计: %s
|
||||||
|
issues.change_time_estimate_at=预估时间已修改为 <b>%[1]s</b> %[2]s
|
||||||
issues.remove_time_estimate_at=删除预计时间 %s
|
issues.remove_time_estimate_at=删除预计时间 %s
|
||||||
issues.time_estimate_invalid=预计时间格式无效
|
issues.time_estimate_invalid=预计时间格式无效
|
||||||
issues.start_tracking_history=`开始工作 %s`
|
issues.start_tracking_history=`开始工作 %s`
|
||||||
issues.tracker_auto_close=当此工单关闭时,自动停止计时器
|
issues.tracker_auto_close=当此工单关闭时,自动停止计时器
|
||||||
issues.tracking_already_started=`你已经开始对 <a href="%s">另一个工单</a> 进行时间跟踪!`
|
issues.tracking_already_started=`你已经开始对 <a href="%s">另一个工单</a> 进行时间跟踪!`
|
||||||
|
issues.stop_tracking=停止计时器
|
||||||
issues.cancel_tracking_history=`取消时间跟踪 %s`
|
issues.cancel_tracking_history=`取消时间跟踪 %s`
|
||||||
issues.del_time=删除此时间跟踪日志
|
issues.del_time=删除此时间跟踪日志
|
||||||
issues.del_time_history=`已删除时间 %s`
|
issues.del_time_history=`已删除时间 %s`
|
||||||
@ -1912,6 +1942,7 @@ pulls.outdated_with_base_branch=此分支相比基础分支已过期
|
|||||||
pulls.close=关闭合并请求
|
pulls.close=关闭合并请求
|
||||||
pulls.closed_at=`于 <a id="%[1]s" href="#%[1]s">%[2]s</a> 关闭此合并请求 `
|
pulls.closed_at=`于 <a id="%[1]s" href="#%[1]s">%[2]s</a> 关闭此合并请求 `
|
||||||
pulls.reopened_at=`重新打开此合并请求 <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
pulls.reopened_at=`重新打开此合并请求 <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
|
pulls.cmd_instruction_hint=查看命令行提示
|
||||||
pulls.cmd_instruction_checkout_title=检出
|
pulls.cmd_instruction_checkout_title=检出
|
||||||
pulls.cmd_instruction_checkout_desc=从你的仓库中检出一个新的分支并测试变更。
|
pulls.cmd_instruction_checkout_desc=从你的仓库中检出一个新的分支并测试变更。
|
||||||
pulls.cmd_instruction_merge_title=合并
|
pulls.cmd_instruction_merge_title=合并
|
||||||
@ -2099,6 +2130,7 @@ contributors.contribution_type.deletions=删除
|
|||||||
settings=设置
|
settings=设置
|
||||||
settings.desc=设置是你可以管理仓库设置的地方
|
settings.desc=设置是你可以管理仓库设置的地方
|
||||||
settings.options=仓库
|
settings.options=仓库
|
||||||
|
settings.public_access=公开访问
|
||||||
settings.collaboration=协作者
|
settings.collaboration=协作者
|
||||||
settings.collaboration.admin=管理员
|
settings.collaboration.admin=管理员
|
||||||
settings.collaboration.write=可写权限
|
settings.collaboration.write=可写权限
|
||||||
@ -2312,6 +2344,8 @@ settings.event_fork=派生
|
|||||||
settings.event_fork_desc=仓库被派生。
|
settings.event_fork_desc=仓库被派生。
|
||||||
settings.event_wiki=百科
|
settings.event_wiki=百科
|
||||||
settings.event_wiki_desc=创建、重命名、编辑或删除了百科页面。
|
settings.event_wiki_desc=创建、重命名、编辑或删除了百科页面。
|
||||||
|
settings.event_statuses=状态
|
||||||
|
settings.event_statuses_desc=已从 API 更新提交状态。
|
||||||
settings.event_release=版本发布
|
settings.event_release=版本发布
|
||||||
settings.event_release_desc=发布、更新或删除版本时。
|
settings.event_release_desc=发布、更新或删除版本时。
|
||||||
settings.event_push=推送
|
settings.event_push=推送
|
||||||
@ -2349,6 +2383,8 @@ settings.event_pull_request_review_request=发起合并请求评审
|
|||||||
settings.event_pull_request_review_request_desc=合并请求评审已请求或已取消
|
settings.event_pull_request_review_request_desc=合并请求评审已请求或已取消
|
||||||
settings.event_pull_request_approvals=合并请求批准
|
settings.event_pull_request_approvals=合并请求批准
|
||||||
settings.event_pull_request_merge=合并请求合并
|
settings.event_pull_request_merge=合并请求合并
|
||||||
|
settings.event_header_workflow=工作流程事件
|
||||||
|
settings.event_workflow_job=工作流任务
|
||||||
settings.event_package=软件包
|
settings.event_package=软件包
|
||||||
settings.event_package_desc=软件包已在仓库中被创建或删除。
|
settings.event_package_desc=软件包已在仓库中被创建或删除。
|
||||||
settings.branch_filter=分支过滤
|
settings.branch_filter=分支过滤
|
||||||
@ -2611,6 +2647,9 @@ diff.image.overlay=叠加
|
|||||||
diff.has_escaped=这一行有隐藏的 Unicode 字符
|
diff.has_escaped=这一行有隐藏的 Unicode 字符
|
||||||
diff.show_file_tree=显示文件树
|
diff.show_file_tree=显示文件树
|
||||||
diff.hide_file_tree=隐藏文件树
|
diff.hide_file_tree=隐藏文件树
|
||||||
|
diff.submodule_added=子模块 %[1]s 已添加到 %[2]s
|
||||||
|
diff.submodule_deleted=子模块 %[1]s 已从 %[2]s 中删除
|
||||||
|
diff.submodule_updated=子模块 %[1]s 已更新:%[2]s
|
||||||
|
|
||||||
releases.desc=跟踪项目版本和下载。
|
releases.desc=跟踪项目版本和下载。
|
||||||
release.releases=版本发布
|
release.releases=版本发布
|
||||||
@ -2681,6 +2720,7 @@ branch.restore_success=分支 "%s"已还原。
|
|||||||
branch.restore_failed=还原分支 "%s"失败。
|
branch.restore_failed=还原分支 "%s"失败。
|
||||||
branch.protected_deletion_failed=不能删除受保护的分支 "%s"。
|
branch.protected_deletion_failed=不能删除受保护的分支 "%s"。
|
||||||
branch.default_deletion_failed=不能删除默认分支"%s"。
|
branch.default_deletion_failed=不能删除默认分支"%s"。
|
||||||
|
branch.default_branch_not_exist=默认分支 %s 不存在。
|
||||||
branch.restore=`还原分支 "%s"`
|
branch.restore=`还原分支 "%s"`
|
||||||
branch.download=`下载分支 "%s"`
|
branch.download=`下载分支 "%s"`
|
||||||
branch.rename=`重命名分支 "%s"`
|
branch.rename=`重命名分支 "%s"`
|
||||||
@ -2695,6 +2735,8 @@ branch.create_branch_operation=创建分支
|
|||||||
branch.new_branch=创建新分支
|
branch.new_branch=创建新分支
|
||||||
branch.new_branch_from=基于"%s"创建新分支
|
branch.new_branch_from=基于"%s"创建新分支
|
||||||
branch.renamed=分支 %s 被重命名为 %s。
|
branch.renamed=分支 %s 被重命名为 %s。
|
||||||
|
branch.rename_default_or_protected_branch_error=只有管理员能重命名默认分支和受保护的分支。
|
||||||
|
branch.rename_protected_branch_failed=此分支受到 glob 语法规则的保护。
|
||||||
|
|
||||||
tag.create_tag=创建标签 %s
|
tag.create_tag=创建标签 %s
|
||||||
tag.create_tag_operation=创建标签
|
tag.create_tag_operation=创建标签
|
||||||
@ -2849,7 +2891,15 @@ teams.invite.title=您已被邀请加入组织 <strong>%s</strong> 中的团队
|
|||||||
teams.invite.by=邀请人 %s
|
teams.invite.by=邀请人 %s
|
||||||
teams.invite.description=请点击下面的按钮加入团队。
|
teams.invite.description=请点击下面的按钮加入团队。
|
||||||
|
|
||||||
|
view_as_role=以 %s 身份查看
|
||||||
|
view_as_public_hint=您正在以公开用户的身份查看 README
|
||||||
|
view_as_member_hint=您正在以组织成员的身份查看 README
|
||||||
|
|
||||||
|
worktime=工作时间
|
||||||
|
worktime.date_range_start=起始日期
|
||||||
|
worktime.date_range_end=结束日期
|
||||||
|
worktime.query=查询
|
||||||
|
worktime.time=时间
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
maintenance=维护
|
maintenance=维护
|
||||||
@ -3343,6 +3393,7 @@ monitor.previous=上次执行时间
|
|||||||
monitor.execute_times=执行次数
|
monitor.execute_times=执行次数
|
||||||
monitor.process=运行中进程
|
monitor.process=运行中进程
|
||||||
monitor.stacktrace=调用栈踪迹
|
monitor.stacktrace=调用栈踪迹
|
||||||
|
monitor.trace=追踪
|
||||||
monitor.performance_logs=性能日志
|
monitor.performance_logs=性能日志
|
||||||
monitor.processes_count=%d 个进程
|
monitor.processes_count=%d 个进程
|
||||||
monitor.download_diagnosis_report=下载诊断报告
|
monitor.download_diagnosis_report=下载诊断报告
|
||||||
@ -3518,10 +3569,11 @@ versions=版本
|
|||||||
versions.view_all=查看全部
|
versions.view_all=查看全部
|
||||||
dependency.id=ID
|
dependency.id=ID
|
||||||
dependency.version=版本
|
dependency.version=版本
|
||||||
|
search_in_external_registry=在 %s 中搜索
|
||||||
alpine.registry=通过在您的 <code>/etc/apk/repositories</code> 文件中添加 URL 来设置此注册中心:
|
alpine.registry=通过在您的 <code>/etc/apk/repositories</code> 文件中添加 URL 来设置此注册中心:
|
||||||
alpine.registry.key=下载注册中心公开的 RSA 密钥到 <code>/etc/apk/keys/</code> 文件夹来验证索引签名:
|
alpine.registry.key=下载注册中心公开的 RSA 密钥到 <code>/etc/apk/keys/</code> 文件夹来验证索引签名:
|
||||||
alpine.registry.info=从下面的列表中选择 $branch 和 $repository。
|
alpine.registry.info=从下面的列表中选择 $branch 和 $repository。
|
||||||
alpine.install=要安装包,请运行以下命令:
|
alpine.install=要安装软件包,请运行以下命令:
|
||||||
alpine.repository=仓库信息
|
alpine.repository=仓库信息
|
||||||
alpine.repository.branches=分支
|
alpine.repository.branches=分支
|
||||||
alpine.repository.repositories=仓库
|
alpine.repository.repositories=仓库
|
||||||
@ -3534,7 +3586,7 @@ arch.repository.architectures=架构
|
|||||||
cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:<code>~/.cargo/config.toml</code>):
|
cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:<code>~/.cargo/config.toml</code>):
|
||||||
cargo.install=要使用 Cargo 安装软件包,请运行以下命令:
|
cargo.install=要使用 Cargo 安装软件包,请运行以下命令:
|
||||||
chef.registry=在您的 <code>~/.chef/config.rb</code> 文件中设置此注册中心:
|
chef.registry=在您的 <code>~/.chef/config.rb</code> 文件中设置此注册中心:
|
||||||
chef.install=要安装包,请运行以下命令:
|
chef.install=要安装软件包,请运行以下命令:
|
||||||
composer.registry=在您的 <code>~/.composer/config.json</code> 文件中设置此注册中心:
|
composer.registry=在您的 <code>~/.composer/config.json</code> 文件中设置此注册中心:
|
||||||
composer.install=要使用 Composer 安装软件包,请运行以下命令:
|
composer.install=要使用 Composer 安装软件包,请运行以下命令:
|
||||||
composer.dependencies=依赖
|
composer.dependencies=依赖
|
||||||
@ -3548,16 +3600,17 @@ container.details.type=镜像类型
|
|||||||
container.details.platform=平台
|
container.details.platform=平台
|
||||||
container.pull=从命令行拉取镜像:
|
container.pull=从命令行拉取镜像:
|
||||||
container.images=镜像
|
container.images=镜像
|
||||||
|
container.digest=摘要
|
||||||
container.multi_arch=OS / Arch
|
container.multi_arch=OS / Arch
|
||||||
container.layers=镜像层
|
container.layers=镜像层
|
||||||
container.labels=标签
|
container.labels=标签
|
||||||
container.labels.key=键
|
container.labels.key=键
|
||||||
container.labels.value=值
|
container.labels.value=值
|
||||||
cran.registry=在您的 <code>Rprofile.site</code> 文件中设置此注册中心:
|
cran.registry=在您的 <code>Rprofile.site</code> 文件中设置此注册中心:
|
||||||
cran.install=要安装包,请运行以下命令:
|
cran.install=要安装软件包,请运行以下命令:
|
||||||
debian.registry=从命令行设置此注册中心:
|
debian.registry=从命令行设置此注册中心:
|
||||||
debian.registry.info=从下面的列表中选择 $distribution 和 $component。
|
debian.registry.info=从下面的列表中选择 $distribution 和 $component。
|
||||||
debian.install=要安装包,请运行以下命令:
|
debian.install=要安装软件包,请运行以下命令:
|
||||||
debian.repository=仓库信息
|
debian.repository=仓库信息
|
||||||
debian.repository.distributions=发行版
|
debian.repository.distributions=发行版
|
||||||
debian.repository.components=组件
|
debian.repository.components=组件
|
||||||
@ -3588,7 +3641,7 @@ pypi.install=要使用 pip 安装软件包,请运行以下命令:
|
|||||||
rpm.registry=从命令行设置此注册中心:
|
rpm.registry=从命令行设置此注册中心:
|
||||||
rpm.distros.redhat=在基于 RedHat 的发行版
|
rpm.distros.redhat=在基于 RedHat 的发行版
|
||||||
rpm.distros.suse=在基于 SUSE 的发行版
|
rpm.distros.suse=在基于 SUSE 的发行版
|
||||||
rpm.install=要安装包,请运行以下命令:
|
rpm.install=要安装软件包,请运行以下命令:
|
||||||
rpm.repository=仓库信息
|
rpm.repository=仓库信息
|
||||||
rpm.repository.architectures=架构
|
rpm.repository.architectures=架构
|
||||||
rpm.repository.multiple_groups=此软件包可在多个组中使用。
|
rpm.repository.multiple_groups=此软件包可在多个组中使用。
|
||||||
@ -3654,6 +3707,7 @@ creation=添加密钥
|
|||||||
creation.description=组织描述
|
creation.description=组织描述
|
||||||
creation.name_placeholder=不区分大小写,字母数字或下划线不能以GITEA_ 或 GITHUB_ 开头。
|
creation.name_placeholder=不区分大小写,字母数字或下划线不能以GITEA_ 或 GITHUB_ 开头。
|
||||||
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略
|
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略
|
||||||
|
creation.description_placeholder=输入简短描述(可选)。
|
||||||
creation.success=您的密钥 '%s' 添加成功。
|
creation.success=您的密钥 '%s' 添加成功。
|
||||||
creation.failed=添加密钥失败。
|
creation.failed=添加密钥失败。
|
||||||
deletion=删除密钥
|
deletion=删除密钥
|
||||||
@ -3684,7 +3738,7 @@ runners.status=状态
|
|||||||
runners.id=ID
|
runners.id=ID
|
||||||
runners.name=名称
|
runners.name=名称
|
||||||
runners.owner_type=类型
|
runners.owner_type=类型
|
||||||
runners.description=组织描述
|
runners.description=描述
|
||||||
runners.labels=标签
|
runners.labels=标签
|
||||||
runners.last_online=上次在线时间
|
runners.last_online=上次在线时间
|
||||||
runners.runner_title=Runner
|
runners.runner_title=Runner
|
||||||
@ -3707,10 +3761,11 @@ runners.delete_runner_notice=如果一个任务正在运行在此运行器上,
|
|||||||
runners.none=无可用的 Runner
|
runners.none=无可用的 Runner
|
||||||
runners.status.unspecified=未知
|
runners.status.unspecified=未知
|
||||||
runners.status.idle=空闲
|
runners.status.idle=空闲
|
||||||
runners.status.active=激活
|
runners.status.active=启用
|
||||||
runners.status.offline=离线
|
runners.status.offline=离线
|
||||||
runners.version=版本
|
runners.version=版本
|
||||||
runners.reset_registration_token=重置注册令牌
|
runners.reset_registration_token=重置注册令牌
|
||||||
|
runners.reset_registration_token_confirm=是否吊销当前令牌并生成一个新令牌?
|
||||||
runners.reset_registration_token_success=成功重置运行器注册令牌
|
runners.reset_registration_token_success=成功重置运行器注册令牌
|
||||||
|
|
||||||
runs.all_workflows=所有工作流
|
runs.all_workflows=所有工作流
|
||||||
@ -3743,6 +3798,7 @@ workflow.not_found=工作流 %s 未找到。
|
|||||||
workflow.run_success=工作流 %s 已成功运行。
|
workflow.run_success=工作流 %s 已成功运行。
|
||||||
workflow.from_ref=使用工作流从
|
workflow.from_ref=使用工作流从
|
||||||
workflow.has_workflow_dispatch=此 Workflow 有一个 Workflow_dispatch 事件触发器。
|
workflow.has_workflow_dispatch=此 Workflow 有一个 Workflow_dispatch 事件触发器。
|
||||||
|
workflow.has_no_workflow_dispatch=工作流 %s 没有 workflow_dispatch 事件的触发器。
|
||||||
|
|
||||||
need_approval_desc=该工作流由派生仓库的合并请求所触发,需要批准方可运行。
|
need_approval_desc=该工作流由派生仓库的合并请求所触发,需要批准方可运行。
|
||||||
|
|
||||||
@ -3762,6 +3818,8 @@ variables.creation.success=变量 “%s” 添加成功。
|
|||||||
variables.update.failed=编辑变量失败。
|
variables.update.failed=编辑变量失败。
|
||||||
variables.update.success=该变量已被编辑。
|
variables.update.success=该变量已被编辑。
|
||||||
|
|
||||||
|
logs.always_auto_scroll=总是自动滚动日志
|
||||||
|
logs.always_expand_running=总是展开运行日志
|
||||||
|
|
||||||
[projects]
|
[projects]
|
||||||
deleted.display_name=已删除项目
|
deleted.display_name=已删除项目
|
||||||
|
@ -20,6 +20,11 @@ func BlockedUsers(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsOrgSettings"] = true
|
ctx.Data["PageIsOrgSettings"] = true
|
||||||
ctx.Data["PageIsSettingsBlockedUsers"] = true
|
ctx.Data["PageIsSettingsBlockedUsers"] = true
|
||||||
|
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
shared_user.BlockedUsers(ctx, ctx.ContextUser)
|
shared_user.BlockedUsers(ctx, ctx.ContextUser)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
@ -29,6 +34,11 @@ func BlockedUsers(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BlockedUsersPost(ctx *context.Context) {
|
func BlockedUsersPost(ctx *context.Context) {
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
shared_user.BlockedUsersPost(ctx, ctx.ContextUser)
|
shared_user.BlockedUsersPost(ctx, ctx.ContextUser)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
|
@ -86,12 +86,6 @@ func home(ctx *context.Context, viewRepositories bool) {
|
|||||||
private := ctx.FormOptionalBool("private")
|
private := ctx.FormOptionalBool("private")
|
||||||
ctx.Data["IsPrivate"] = private
|
ctx.Data["IsPrivate"] = private
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := &organization.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
Doer: ctx.Doer,
|
Doer: ctx.Doer,
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
@ -109,9 +103,9 @@ func home(ctx *context.Context, viewRepositories bool) {
|
|||||||
ctx.Data["DisableNewPullMirrors"] = setting.Mirror.DisableNewPull
|
ctx.Data["DisableNewPullMirrors"] = setting.Mirror.DisableNewPull
|
||||||
ctx.Data["ShowMemberAndTeamTab"] = ctx.Org.IsMember || len(members) > 0
|
ctx.Data["ShowMemberAndTeamTab"] = ctx.Org.IsMember || len(members) > 0
|
||||||
|
|
||||||
prepareResult, err := shared_user.PrepareOrgHeader(ctx)
|
prepareResult, err := shared_user.RenderUserOrgHeader(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("PrepareOrgHeader", err)
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +148,7 @@ func home(ctx *context.Context, viewRepositories bool) {
|
|||||||
ctx.HTML(http.StatusOK, tplOrgHome)
|
ctx.HTML(http.StatusOK, tplOrgHome)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareOrgProfileReadme(ctx *context.Context, prepareResult *shared_user.PrepareOrgHeaderResult) bool {
|
func prepareOrgProfileReadme(ctx *context.Context, prepareResult *shared_user.PrepareOwnerHeaderResult) bool {
|
||||||
viewAs := ctx.FormString("view_as", util.Iif(ctx.Org.IsMember, "member", "public"))
|
viewAs := ctx.FormString("view_as", util.Iif(ctx.Org.IsMember, "member", "public"))
|
||||||
viewAsMember := viewAs == "member"
|
viewAsMember := viewAs == "member"
|
||||||
|
|
||||||
|
@ -54,9 +54,8 @@ func Members(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = shared_user.PrepareOrgHeader(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("PrepareOrgHeader", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,11 +44,12 @@ func NewLabel(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l := &issues_model.Label{
|
l := &issues_model.Label{
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
Name: form.Title,
|
Name: form.Title,
|
||||||
Exclusive: form.Exclusive,
|
Exclusive: form.Exclusive,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
Color: form.Color,
|
Color: form.Color,
|
||||||
|
ExclusiveOrder: form.ExclusiveOrder,
|
||||||
}
|
}
|
||||||
if err := issues_model.NewLabel(ctx, l); err != nil {
|
if err := issues_model.NewLabel(ctx, l); err != nil {
|
||||||
ctx.ServerError("NewLabel", err)
|
ctx.ServerError("NewLabel", err)
|
||||||
@ -73,6 +74,7 @@ func UpdateLabel(ctx *context.Context) {
|
|||||||
|
|
||||||
l.Name = form.Title
|
l.Name = form.Title
|
||||||
l.Exclusive = form.Exclusive
|
l.Exclusive = form.Exclusive
|
||||||
|
l.ExclusiveOrder = form.ExclusiveOrder
|
||||||
l.Description = form.Description
|
l.Description = form.Description
|
||||||
l.Color = form.Color
|
l.Color = form.Color
|
||||||
l.SetArchived(form.IsArchived)
|
l.SetArchived(form.IsArchived)
|
||||||
|
@ -43,7 +43,10 @@ func MustEnableProjects(ctx *context.Context) {
|
|||||||
|
|
||||||
// Projects renders the home page of projects
|
// Projects renders the home page of projects
|
||||||
func Projects(ctx *context.Context) {
|
func Projects(ctx *context.Context) {
|
||||||
shared_user.PrepareContextForProfileBigAvatar(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.projects")
|
ctx.Data["Title"] = ctx.Tr("repo.projects")
|
||||||
|
|
||||||
sortType := ctx.FormTrim("sort")
|
sortType := ctx.FormTrim("sort")
|
||||||
@ -101,7 +104,6 @@ func Projects(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["Projects"] = projects
|
ctx.Data["Projects"] = projects
|
||||||
shared_user.RenderUserHeader(ctx)
|
|
||||||
|
|
||||||
if isShowClosed {
|
if isShowClosed {
|
||||||
ctx.Data["State"] = "closed"
|
ctx.Data["State"] = "closed"
|
||||||
@ -113,12 +115,6 @@ func Projects(ctx *context.Context) {
|
|||||||
project.RenderedContent = renderUtils.MarkdownToHtml(project.Description)
|
project.RenderedContent = renderUtils.MarkdownToHtml(project.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
numPages := 0
|
numPages := 0
|
||||||
if total > 0 {
|
if total > 0 {
|
||||||
numPages = (int(total) - 1/setting.UI.IssuePagingNum)
|
numPages = (int(total) - 1/setting.UI.IssuePagingNum)
|
||||||
@ -152,11 +148,8 @@ func RenderNewProject(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsViewProjects"] = true
|
ctx.Data["PageIsViewProjects"] = true
|
||||||
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
|
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
|
||||||
ctx.Data["CancelLink"] = ctx.ContextUser.HomeLink() + "/-/projects"
|
ctx.Data["CancelLink"] = ctx.ContextUser.HomeLink() + "/-/projects"
|
||||||
shared_user.RenderUserHeader(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +160,10 @@ func RenderNewProject(ctx *context.Context) {
|
|||||||
func NewProjectPost(ctx *context.Context) {
|
func NewProjectPost(ctx *context.Context) {
|
||||||
form := web.GetForm(ctx).(*forms.CreateProjectForm)
|
form := web.GetForm(ctx).(*forms.CreateProjectForm)
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
|
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
|
||||||
shared_user.RenderUserHeader(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
RenderNewProject(ctx)
|
RenderNewProject(ctx)
|
||||||
@ -248,7 +244,10 @@ func RenderEditProject(ctx *context.Context) {
|
|||||||
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
|
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
|
||||||
ctx.Data["CardTypes"] = project_model.GetCardConfig()
|
ctx.Data["CardTypes"] = project_model.GetCardConfig()
|
||||||
|
|
||||||
shared_user.RenderUserHeader(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
p, err := project_model.GetProjectByID(ctx, ctx.PathParamInt64("id"))
|
p, err := project_model.GetProjectByID(ctx, ctx.PathParamInt64("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -282,11 +281,8 @@ func EditProjectPost(ctx *context.Context) {
|
|||||||
ctx.Data["CardTypes"] = project_model.GetCardConfig()
|
ctx.Data["CardTypes"] = project_model.GetCardConfig()
|
||||||
ctx.Data["CancelLink"] = project_model.ProjectLinkForOrg(ctx.ContextUser, projectID)
|
ctx.Data["CancelLink"] = project_model.ProjectLinkForOrg(ctx.ContextUser, projectID)
|
||||||
|
|
||||||
shared_user.RenderUserHeader(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,14 +339,14 @@ func ViewProject(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
labelIDs := issue.PrepareFilterIssueLabels(ctx, project.RepoID, project.Owner)
|
preparedLabelFilter := issue.PrepareFilterIssueLabels(ctx, project.RepoID, project.Owner)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assigneeID := ctx.FormString("assignee")
|
assigneeID := ctx.FormString("assignee")
|
||||||
|
|
||||||
opts := issues_model.IssuesOptions{
|
opts := issues_model.IssuesOptions{
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: preparedLabelFilter.SelectedLabelIDs,
|
||||||
AssigneeID: assigneeID,
|
AssigneeID: assigneeID,
|
||||||
Owner: project.Owner,
|
Owner: project.Owner,
|
||||||
Doer: ctx.Doer,
|
Doer: ctx.Doer,
|
||||||
@ -406,8 +402,8 @@ func ViewProject(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the exclusive scope for every label ID
|
// Get the exclusive scope for every label ID
|
||||||
labelExclusiveScopes := make([]string, 0, len(labelIDs))
|
labelExclusiveScopes := make([]string, 0, len(preparedLabelFilter.SelectedLabelIDs))
|
||||||
for _, labelID := range labelIDs {
|
for _, labelID := range preparedLabelFilter.SelectedLabelIDs {
|
||||||
foundExclusiveScope := false
|
foundExclusiveScope := false
|
||||||
for _, label := range labels {
|
for _, label := range labels {
|
||||||
if label.ID == labelID || label.ID == -labelID {
|
if label.ID == labelID || label.ID == -labelID {
|
||||||
@ -422,7 +418,7 @@ func ViewProject(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range labels {
|
for _, l := range labels {
|
||||||
l.LoadSelectedLabelsAfterClick(labelIDs, labelExclusiveScopes)
|
l.LoadSelectedLabelsAfterClick(preparedLabelFilter.SelectedLabelIDs, labelExclusiveScopes)
|
||||||
}
|
}
|
||||||
ctx.Data["Labels"] = labels
|
ctx.Data["Labels"] = labels
|
||||||
ctx.Data["NumLabels"] = len(labels)
|
ctx.Data["NumLabels"] = len(labels)
|
||||||
@ -443,11 +439,9 @@ func ViewProject(ctx *context.Context) {
|
|||||||
ctx.Data["Project"] = project
|
ctx.Data["Project"] = project
|
||||||
ctx.Data["IssuesMap"] = issuesMap
|
ctx.Data["IssuesMap"] = issuesMap
|
||||||
ctx.Data["Columns"] = columns
|
ctx.Data["Columns"] = columns
|
||||||
shared_user.RenderUserHeader(ctx)
|
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,9 +48,8 @@ func Settings(ctx *context.Context) {
|
|||||||
ctx.Data["RepoAdminChangeTeamAccess"] = ctx.Org.Organization.RepoAdminChangeTeamAccess
|
ctx.Data["RepoAdminChangeTeamAccess"] = ctx.Org.Organization.RepoAdminChangeTeamAccess
|
||||||
ctx.Data["ContextUser"] = ctx.ContextUser
|
ctx.Data["ContextUser"] = ctx.ContextUser
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,9 +193,8 @@ func SettingsDelete(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,9 +216,8 @@ func Webhooks(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,9 +243,8 @@ func Labels(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsOrgSettingsLabels"] = true
|
ctx.Data["PageIsOrgSettingsLabels"] = true
|
||||||
ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles
|
ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,9 +45,8 @@ func Applications(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
ctx.Data["Applications"] = apps
|
ctx.Data["Applications"] = apps
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,8 @@ func Packages(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsOrgSettings"] = true
|
ctx.Data["PageIsOrgSettings"] = true
|
||||||
ctx.Data["PageIsSettingsPackages"] = true
|
ctx.Data["PageIsSettingsPackages"] = true
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,9 +40,8 @@ func PackagesRuleAdd(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsOrgSettings"] = true
|
ctx.Data["PageIsOrgSettings"] = true
|
||||||
ctx.Data["PageIsSettingsPackages"] = true
|
ctx.Data["PageIsSettingsPackages"] = true
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,9 +55,8 @@ func PackagesRuleEdit(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsOrgSettings"] = true
|
ctx.Data["PageIsOrgSettings"] = true
|
||||||
ctx.Data["PageIsSettingsPackages"] = true
|
ctx.Data["PageIsSettingsPackages"] = true
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +96,8 @@ func PackagesRulePreview(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsOrgSettings"] = true
|
ctx.Data["PageIsOrgSettings"] = true
|
||||||
ctx.Data["PageIsSettingsPackages"] = true
|
ctx.Data["PageIsSettingsPackages"] = true
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,10 @@ const (
|
|||||||
|
|
||||||
// Teams render teams list page
|
// Teams render teams list page
|
||||||
func Teams(ctx *context.Context) {
|
func Teams(ctx *context.Context) {
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
org := ctx.Org.Organization
|
org := ctx.Org.Organization
|
||||||
ctx.Data["Title"] = org.FullName
|
ctx.Data["Title"] = org.FullName
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
@ -58,12 +62,6 @@ func Teams(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
ctx.Data["Teams"] = ctx.Org.Teams
|
ctx.Data["Teams"] = ctx.Org.Teams
|
||||||
|
|
||||||
_, err := shared_user.PrepareOrgHeader(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("PrepareOrgHeader", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplTeams)
|
ctx.HTML(http.StatusOK, tplTeams)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,15 +270,15 @@ func TeamsRepoAction(ctx *context.Context) {
|
|||||||
|
|
||||||
// NewTeam render create new team page
|
// NewTeam render create new team page
|
||||||
func NewTeam(ctx *context.Context) {
|
func NewTeam(ctx *context.Context) {
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
ctx.Data["PageIsOrgTeamsNew"] = true
|
ctx.Data["PageIsOrgTeamsNew"] = true
|
||||||
ctx.Data["Team"] = &org_model.Team{}
|
ctx.Data["Team"] = &org_model.Team{}
|
||||||
ctx.Data["Units"] = unit_model.Units
|
ctx.Data["Units"] = unit_model.Units
|
||||||
if err := shared_user.LoadHeaderCount(ctx); err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.HTML(http.StatusOK, tplTeamNew)
|
ctx.HTML(http.StatusOK, tplTeamNew)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,15 +368,15 @@ func NewTeamPost(ctx *context.Context) {
|
|||||||
|
|
||||||
// TeamMembers render team members page
|
// TeamMembers render team members page
|
||||||
func TeamMembers(ctx *context.Context) {
|
func TeamMembers(ctx *context.Context) {
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["Title"] = ctx.Org.Team.Name
|
ctx.Data["Title"] = ctx.Org.Team.Name
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
ctx.Data["PageIsOrgTeamMembers"] = true
|
ctx.Data["PageIsOrgTeamMembers"] = true
|
||||||
|
|
||||||
if err := shared_user.LoadHeaderCount(ctx); err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.Org.Team.LoadMembers(ctx); err != nil {
|
if err := ctx.Org.Team.LoadMembers(ctx); err != nil {
|
||||||
ctx.ServerError("GetMembers", err)
|
ctx.ServerError("GetMembers", err)
|
||||||
return
|
return
|
||||||
@ -398,15 +396,15 @@ func TeamMembers(ctx *context.Context) {
|
|||||||
|
|
||||||
// TeamRepositories show the repositories of team
|
// TeamRepositories show the repositories of team
|
||||||
func TeamRepositories(ctx *context.Context) {
|
func TeamRepositories(ctx *context.Context) {
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["Title"] = ctx.Org.Team.Name
|
ctx.Data["Title"] = ctx.Org.Team.Name
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
ctx.Data["PageIsOrgTeamRepos"] = true
|
ctx.Data["PageIsOrgTeamRepos"] = true
|
||||||
|
|
||||||
if err := shared_user.LoadHeaderCount(ctx); err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
||||||
TeamID: ctx.Org.Team.ID,
|
TeamID: ctx.Org.Team.ID,
|
||||||
})
|
})
|
||||||
@ -463,16 +461,16 @@ func SearchTeam(ctx *context.Context) {
|
|||||||
|
|
||||||
// EditTeam render team edit page
|
// EditTeam render team edit page
|
||||||
func EditTeam(ctx *context.Context) {
|
func EditTeam(ctx *context.Context) {
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
if err := ctx.Org.Team.LoadUnits(ctx); err != nil {
|
if err := ctx.Org.Team.LoadUnits(ctx); err != nil {
|
||||||
ctx.ServerError("LoadUnits", err)
|
ctx.ServerError("LoadUnits", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := shared_user.LoadHeaderCount(ctx); err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["Team"] = ctx.Org.Team
|
ctx.Data["Team"] = ctx.Org.Team
|
||||||
ctx.Data["Units"] = unit_model.Units
|
ctx.Data["Units"] = unit_model.Units
|
||||||
ctx.HTML(http.StatusOK, tplTeamNew)
|
ctx.HTML(http.StatusOK, tplTeamNew)
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/modules/templates"
|
"code.gitea.io/gitea/modules/templates"
|
||||||
|
shared_user "code.gitea.io/gitea/routers/web/shared/user"
|
||||||
"code.gitea.io/gitea/services/context"
|
"code.gitea.io/gitea/services/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,6 +71,12 @@ func Worktime(ctx *context.Context) {
|
|||||||
ctx.ServerError("GetWorktime", err)
|
ctx.ServerError("GetWorktime", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["WorktimeSumResult"] = worktimeSumResult
|
ctx.Data["WorktimeSumResult"] = worktimeSumResult
|
||||||
ctx.HTML(http.StatusOK, tplByRepos)
|
ctx.HTML(http.StatusOK, tplByRepos)
|
||||||
}
|
}
|
||||||
|
@ -111,11 +111,12 @@ func NewLabel(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l := &issues_model.Label{
|
l := &issues_model.Label{
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
Name: form.Title,
|
Name: form.Title,
|
||||||
Exclusive: form.Exclusive,
|
Exclusive: form.Exclusive,
|
||||||
Description: form.Description,
|
ExclusiveOrder: form.ExclusiveOrder,
|
||||||
Color: form.Color,
|
Description: form.Description,
|
||||||
|
Color: form.Color,
|
||||||
}
|
}
|
||||||
if err := issues_model.NewLabel(ctx, l); err != nil {
|
if err := issues_model.NewLabel(ctx, l); err != nil {
|
||||||
ctx.ServerError("NewLabel", err)
|
ctx.ServerError("NewLabel", err)
|
||||||
@ -139,6 +140,7 @@ func UpdateLabel(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
l.Name = form.Title
|
l.Name = form.Title
|
||||||
l.Exclusive = form.Exclusive
|
l.Exclusive = form.Exclusive
|
||||||
|
l.ExclusiveOrder = form.ExclusiveOrder
|
||||||
l.Description = form.Description
|
l.Description = form.Description
|
||||||
l.Color = form.Color
|
l.Color = form.Color
|
||||||
|
|
||||||
|
@ -5,8 +5,10 @@ package repo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"maps"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -18,6 +20,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
|
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
|
||||||
|
db_indexer "code.gitea.io/gitea/modules/indexer/issues/db"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@ -30,14 +33,6 @@ import (
|
|||||||
pull_service "code.gitea.io/gitea/services/pull"
|
pull_service "code.gitea.io/gitea/services/pull"
|
||||||
)
|
)
|
||||||
|
|
||||||
func issueIDsFromSearch(ctx *context.Context, keyword string, opts *issues_model.IssuesOptions) ([]int64, error) {
|
|
||||||
ids, _, err := issue_indexer.SearchIssues(ctx, issue_indexer.ToSearchOptions(keyword, opts))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("SearchIssues: %w", err)
|
|
||||||
}
|
|
||||||
return ids, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func retrieveProjectsForIssueList(ctx *context.Context, repo *repo_model.Repository) {
|
func retrieveProjectsForIssueList(ctx *context.Context, repo *repo_model.Repository) {
|
||||||
ctx.Data["OpenProjects"], ctx.Data["ClosedProjects"] = retrieveProjectsInternal(ctx, repo)
|
ctx.Data["OpenProjects"], ctx.Data["ClosedProjects"] = retrieveProjectsInternal(ctx, repo)
|
||||||
}
|
}
|
||||||
@ -459,6 +454,19 @@ func UpdateIssueStatus(ctx *context.Context) {
|
|||||||
ctx.JSONOK()
|
ctx.JSONOK()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prepareIssueFilterExclusiveOrderScopes(ctx *context.Context, allLabels []*issues_model.Label) {
|
||||||
|
scopeSet := make(map[string]bool)
|
||||||
|
for _, label := range allLabels {
|
||||||
|
scope := label.ExclusiveScope()
|
||||||
|
if len(scope) > 0 && label.ExclusiveOrder > 0 {
|
||||||
|
scopeSet[scope] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scopes := slices.Collect(maps.Keys(scopeSet))
|
||||||
|
sort.Strings(scopes)
|
||||||
|
ctx.Data["ExclusiveLabelScopes"] = scopes
|
||||||
|
}
|
||||||
|
|
||||||
func renderMilestones(ctx *context.Context) {
|
func renderMilestones(ctx *context.Context) {
|
||||||
// Get milestones
|
// Get milestones
|
||||||
milestones, err := db.Find[issues_model.Milestone](ctx, issues_model.FindMilestoneOptions{
|
milestones, err := db.Find[issues_model.Milestone](ctx, issues_model.FindMilestoneOptions{
|
||||||
@ -481,7 +489,7 @@ func renderMilestones(ctx *context.Context) {
|
|||||||
ctx.Data["ClosedMilestones"] = closedMilestones
|
ctx.Data["ClosedMilestones"] = closedMilestones
|
||||||
}
|
}
|
||||||
|
|
||||||
func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption optional.Option[bool]) {
|
func prepareIssueFilterAndList(ctx *context.Context, milestoneID, projectID int64, isPullOption optional.Option[bool]) {
|
||||||
var err error
|
var err error
|
||||||
viewType := ctx.FormString("type")
|
viewType := ctx.FormString("type")
|
||||||
sortType := ctx.FormString("sort")
|
sortType := ctx.FormString("sort")
|
||||||
@ -521,15 +529,18 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
|||||||
mileIDs = []int64{milestoneID}
|
mileIDs = []int64{milestoneID}
|
||||||
}
|
}
|
||||||
|
|
||||||
labelIDs := issue.PrepareFilterIssueLabels(ctx, repo.ID, ctx.Repo.Owner)
|
preparedLabelFilter := issue.PrepareFilterIssueLabels(ctx, repo.ID, ctx.Repo.Owner)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepareIssueFilterExclusiveOrderScopes(ctx, preparedLabelFilter.AllLabels)
|
||||||
|
|
||||||
|
var keywordMatchedIssueIDs []int64
|
||||||
var issueStats *issues_model.IssueStats
|
var issueStats *issues_model.IssueStats
|
||||||
statsOpts := &issues_model.IssuesOptions{
|
statsOpts := &issues_model.IssuesOptions{
|
||||||
RepoIDs: []int64{repo.ID},
|
RepoIDs: []int64{repo.ID},
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: preparedLabelFilter.SelectedLabelIDs,
|
||||||
MilestoneIDs: mileIDs,
|
MilestoneIDs: mileIDs,
|
||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
AssigneeID: assigneeID,
|
AssigneeID: assigneeID,
|
||||||
@ -541,7 +552,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
|||||||
IssueIDs: nil,
|
IssueIDs: nil,
|
||||||
}
|
}
|
||||||
if keyword != "" {
|
if keyword != "" {
|
||||||
allIssueIDs, err := issueIDsFromSearch(ctx, keyword, statsOpts)
|
keywordMatchedIssueIDs, _, err = issue_indexer.SearchIssues(ctx, issue_indexer.ToSearchOptions(keyword, statsOpts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if issue_indexer.IsAvailable(ctx) {
|
if issue_indexer.IsAvailable(ctx) {
|
||||||
ctx.ServerError("issueIDsFromSearch", err)
|
ctx.ServerError("issueIDsFromSearch", err)
|
||||||
@ -550,14 +561,17 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
|||||||
ctx.Data["IssueIndexerUnavailable"] = true
|
ctx.Data["IssueIndexerUnavailable"] = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
statsOpts.IssueIDs = allIssueIDs
|
if len(keywordMatchedIssueIDs) == 0 {
|
||||||
|
// It did search with the keyword, but no issue found, just set issueStats to empty, then no need to do query again.
|
||||||
|
issueStats = &issues_model.IssueStats{}
|
||||||
|
// set keywordMatchedIssueIDs to empty slice, so we can distinguish it from "nil"
|
||||||
|
keywordMatchedIssueIDs = []int64{}
|
||||||
|
}
|
||||||
|
statsOpts.IssueIDs = keywordMatchedIssueIDs
|
||||||
}
|
}
|
||||||
if keyword != "" && len(statsOpts.IssueIDs) == 0 {
|
|
||||||
// So it did search with the keyword, but no issue found.
|
if issueStats == nil {
|
||||||
// Just set issueStats to empty.
|
// Either it did search with the keyword, and found some issues, it needs to get issueStats of these issues.
|
||||||
issueStats = &issues_model.IssueStats{}
|
|
||||||
} else {
|
|
||||||
// So it did search with the keyword, and found some issues. It needs to get issueStats of these issues.
|
|
||||||
// Or the keyword is empty, so it doesn't need issueIDs as filter, just get issueStats with statsOpts.
|
// Or the keyword is empty, so it doesn't need issueIDs as filter, just get issueStats with statsOpts.
|
||||||
issueStats, err = issues_model.GetIssueStats(ctx, statsOpts)
|
issueStats, err = issues_model.GetIssueStats(ctx, statsOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -589,25 +603,21 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
|||||||
ctx.Data["TotalTrackedTime"] = totalTrackedTime
|
ctx.Data["TotalTrackedTime"] = totalTrackedTime
|
||||||
}
|
}
|
||||||
|
|
||||||
page := ctx.FormInt("page")
|
// prepare pager
|
||||||
if page <= 1 {
|
total := int(issueStats.OpenCount + issueStats.ClosedCount)
|
||||||
page = 1
|
if isShowClosed.Has() {
|
||||||
}
|
total = util.Iif(isShowClosed.Value(), int(issueStats.ClosedCount), int(issueStats.OpenCount))
|
||||||
|
|
||||||
var total int
|
|
||||||
switch {
|
|
||||||
case isShowClosed.Value():
|
|
||||||
total = int(issueStats.ClosedCount)
|
|
||||||
case !isShowClosed.Has():
|
|
||||||
total = int(issueStats.OpenCount + issueStats.ClosedCount)
|
|
||||||
default:
|
|
||||||
total = int(issueStats.OpenCount)
|
|
||||||
}
|
}
|
||||||
|
page := max(ctx.FormInt("page"), 1)
|
||||||
pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
|
pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
|
||||||
|
|
||||||
|
// prepare real issue list:
|
||||||
var issues issues_model.IssueList
|
var issues issues_model.IssueList
|
||||||
{
|
if keywordMatchedIssueIDs == nil || len(keywordMatchedIssueIDs) > 0 {
|
||||||
ids, err := issueIDsFromSearch(ctx, keyword, &issues_model.IssuesOptions{
|
// Either it did search with the keyword, and found some issues, then keywordMatchedIssueIDs is not null, it needs to use db indexer.
|
||||||
|
// Or the keyword is empty, it also needs to usd db indexer.
|
||||||
|
// In either case, no need to use keyword anymore
|
||||||
|
searchResult, err := db_indexer.GetIndexer().FindWithIssueOptions(ctx, &issues_model.IssuesOptions{
|
||||||
Paginator: &db.ListOptions{
|
Paginator: &db.ListOptions{
|
||||||
Page: pager.Paginater.Current(),
|
Page: pager.Paginater.Current(),
|
||||||
PageSize: setting.UI.IssuePagingNum,
|
PageSize: setting.UI.IssuePagingNum,
|
||||||
@ -622,18 +632,16 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
|||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
IsClosed: isShowClosed,
|
IsClosed: isShowClosed,
|
||||||
IsPull: isPullOption,
|
IsPull: isPullOption,
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: preparedLabelFilter.SelectedLabelIDs,
|
||||||
SortType: sortType,
|
SortType: sortType,
|
||||||
|
IssueIDs: keywordMatchedIssueIDs,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if issue_indexer.IsAvailable(ctx) {
|
ctx.ServerError("DBIndexer.Search", err)
|
||||||
ctx.ServerError("issueIDsFromSearch", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["IssueIndexerUnavailable"] = true
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
issues, err = issues_model.GetIssuesByIDs(ctx, ids, true)
|
issueIDs := issue_indexer.SearchResultToIDSlice(searchResult)
|
||||||
|
issues, err = issues_model.GetIssuesByIDs(ctx, issueIDs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetIssuesByIDs", err)
|
ctx.ServerError("GetIssuesByIDs", err)
|
||||||
return
|
return
|
||||||
@ -728,7 +736,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
|||||||
ctx.Data["IssueStats"] = issueStats
|
ctx.Data["IssueStats"] = issueStats
|
||||||
ctx.Data["OpenCount"] = issueStats.OpenCount
|
ctx.Data["OpenCount"] = issueStats.OpenCount
|
||||||
ctx.Data["ClosedCount"] = issueStats.ClosedCount
|
ctx.Data["ClosedCount"] = issueStats.ClosedCount
|
||||||
ctx.Data["SelLabelIDs"] = labelIDs
|
ctx.Data["SelLabelIDs"] = preparedLabelFilter.SelectedLabelIDs
|
||||||
ctx.Data["ViewType"] = viewType
|
ctx.Data["ViewType"] = viewType
|
||||||
ctx.Data["SortType"] = sortType
|
ctx.Data["SortType"] = sortType
|
||||||
ctx.Data["MilestoneID"] = milestoneID
|
ctx.Data["MilestoneID"] = milestoneID
|
||||||
@ -769,7 +777,7 @@ func Issues(ctx *context.Context) {
|
|||||||
ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||||
}
|
}
|
||||||
|
|
||||||
issues(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), optional.Some(isPullList))
|
prepareIssueFilterAndList(ctx, ctx.FormInt64("milestone"), ctx.FormInt64("project"), optional.Some(isPullList))
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ func MilestoneIssuesAndPulls(ctx *context.Context) {
|
|||||||
ctx.Data["Title"] = milestone.Name
|
ctx.Data["Title"] = milestone.Name
|
||||||
ctx.Data["Milestone"] = milestone
|
ctx.Data["Milestone"] = milestone
|
||||||
|
|
||||||
issues(ctx, milestoneID, projectID, optional.None[bool]())
|
prepareIssueFilterAndList(ctx, milestoneID, projectID, optional.None[bool]())
|
||||||
|
|
||||||
ret := issue.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
ret := issue.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
|
||||||
ctx.Data["NewIssueChooseTemplate"] = len(ret.IssueTemplates) > 0
|
ctx.Data["NewIssueChooseTemplate"] = len(ret.IssueTemplates) > 0
|
||||||
|
@ -313,13 +313,13 @@ func ViewProject(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
labelIDs := issue.PrepareFilterIssueLabels(ctx, ctx.Repo.Repository.ID, ctx.Repo.Owner)
|
preparedLabelFilter := issue.PrepareFilterIssueLabels(ctx, ctx.Repo.Repository.ID, ctx.Repo.Owner)
|
||||||
|
|
||||||
assigneeID := ctx.FormString("assignee")
|
assigneeID := ctx.FormString("assignee")
|
||||||
|
|
||||||
issuesMap, err := project_service.LoadIssuesFromProject(ctx, project, &issues_model.IssuesOptions{
|
issuesMap, err := project_service.LoadIssuesFromProject(ctx, project, &issues_model.IssuesOptions{
|
||||||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: preparedLabelFilter.SelectedLabelIDs,
|
||||||
AssigneeID: assigneeID,
|
AssigneeID: assigneeID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -381,8 +381,8 @@ func ViewProject(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the exclusive scope for every label ID
|
// Get the exclusive scope for every label ID
|
||||||
labelExclusiveScopes := make([]string, 0, len(labelIDs))
|
labelExclusiveScopes := make([]string, 0, len(preparedLabelFilter.SelectedLabelIDs))
|
||||||
for _, labelID := range labelIDs {
|
for _, labelID := range preparedLabelFilter.SelectedLabelIDs {
|
||||||
foundExclusiveScope := false
|
foundExclusiveScope := false
|
||||||
for _, label := range labels {
|
for _, label := range labels {
|
||||||
if label.ID == labelID || label.ID == -labelID {
|
if label.ID == labelID || label.ID == -labelID {
|
||||||
@ -397,7 +397,7 @@ func ViewProject(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range labels {
|
for _, l := range labels {
|
||||||
l.LoadSelectedLabelsAfterClick(labelIDs, labelExclusiveScopes)
|
l.LoadSelectedLabelsAfterClick(preparedLabelFilter.SelectedLabelIDs, labelExclusiveScopes)
|
||||||
}
|
}
|
||||||
ctx.Data["Labels"] = labels
|
ctx.Data["Labels"] = labels
|
||||||
ctx.Data["NumLabels"] = len(labels)
|
ctx.Data["NumLabels"] = len(labels)
|
||||||
|
@ -44,9 +44,8 @@ func getSecretsCtx(ctx *context.Context) (*secretsCtx, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Data["PageIsOrgSettings"] == true {
|
if ctx.Data["PageIsOrgSettings"] == true {
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return &secretsCtx{
|
return &secretsCtx{
|
||||||
|
@ -57,9 +57,8 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Data["PageIsOrgSettings"] == true {
|
if ctx.Data["PageIsOrgSettings"] == true {
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return &runnersCtx{
|
return &runnersCtx{
|
||||||
|
@ -49,9 +49,8 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Data["PageIsOrgSettings"] == true {
|
if ctx.Data["PageIsOrgSettings"] == true {
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return &variablesCtx{
|
return &variablesCtx{
|
||||||
|
@ -14,14 +14,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// PrepareFilterIssueLabels reads the "labels" query parameter, sets `ctx.Data["Labels"]` and `ctx.Data["SelectLabels"]`
|
// PrepareFilterIssueLabels reads the "labels" query parameter, sets `ctx.Data["Labels"]` and `ctx.Data["SelectLabels"]`
|
||||||
func PrepareFilterIssueLabels(ctx *context.Context, repoID int64, owner *user_model.User) (labelIDs []int64) {
|
func PrepareFilterIssueLabels(ctx *context.Context, repoID int64, owner *user_model.User) (ret struct {
|
||||||
|
AllLabels []*issues_model.Label
|
||||||
|
SelectedLabelIDs []int64
|
||||||
|
},
|
||||||
|
) {
|
||||||
// 1,-2 means including label 1 and excluding label 2
|
// 1,-2 means including label 1 and excluding label 2
|
||||||
// 0 means issues with no label
|
// 0 means issues with no label
|
||||||
// blank means labels will not be filtered for issues
|
// blank means labels will not be filtered for issues
|
||||||
selectLabels := ctx.FormString("labels")
|
selectLabels := ctx.FormString("labels")
|
||||||
if selectLabels != "" {
|
if selectLabels != "" {
|
||||||
var err error
|
var err error
|
||||||
labelIDs, err = base.StringsToInt64s(strings.Split(selectLabels, ","))
|
ret.SelectedLabelIDs, err = base.StringsToInt64s(strings.Split(selectLabels, ","))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Flash.Error(ctx.Tr("invalid_data", selectLabels), true)
|
ctx.Flash.Error(ctx.Tr("invalid_data", selectLabels), true)
|
||||||
}
|
}
|
||||||
@ -32,7 +36,7 @@ func PrepareFilterIssueLabels(ctx *context.Context, repoID int64, owner *user_mo
|
|||||||
repoLabels, err := issues_model.GetLabelsByRepoID(ctx, repoID, "", db.ListOptions{})
|
repoLabels, err := issues_model.GetLabelsByRepoID(ctx, repoID, "", db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetLabelsByRepoID", err)
|
ctx.ServerError("GetLabelsByRepoID", err)
|
||||||
return nil
|
return ret
|
||||||
}
|
}
|
||||||
allLabels = append(allLabels, repoLabels...)
|
allLabels = append(allLabels, repoLabels...)
|
||||||
}
|
}
|
||||||
@ -41,14 +45,14 @@ func PrepareFilterIssueLabels(ctx *context.Context, repoID int64, owner *user_mo
|
|||||||
orgLabels, err := issues_model.GetLabelsByOrgID(ctx, owner.ID, "", db.ListOptions{})
|
orgLabels, err := issues_model.GetLabelsByOrgID(ctx, owner.ID, "", db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetLabelsByOrgID", err)
|
ctx.ServerError("GetLabelsByOrgID", err)
|
||||||
return nil
|
return ret
|
||||||
}
|
}
|
||||||
allLabels = append(allLabels, orgLabels...)
|
allLabels = append(allLabels, orgLabels...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the exclusive scope for every label ID
|
// Get the exclusive scope for every label ID
|
||||||
labelExclusiveScopes := make([]string, 0, len(labelIDs))
|
labelExclusiveScopes := make([]string, 0, len(ret.SelectedLabelIDs))
|
||||||
for _, labelID := range labelIDs {
|
for _, labelID := range ret.SelectedLabelIDs {
|
||||||
foundExclusiveScope := false
|
foundExclusiveScope := false
|
||||||
for _, label := range allLabels {
|
for _, label := range allLabels {
|
||||||
if label.ID == labelID || label.ID == -labelID {
|
if label.ID == labelID || label.ID == -labelID {
|
||||||
@ -63,9 +67,10 @@ func PrepareFilterIssueLabels(ctx *context.Context, repoID int64, owner *user_mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range allLabels {
|
for _, l := range allLabels {
|
||||||
l.LoadSelectedLabelsAfterClick(labelIDs, labelExclusiveScopes)
|
l.LoadSelectedLabelsAfterClick(ret.SelectedLabelIDs, labelExclusiveScopes)
|
||||||
}
|
}
|
||||||
ctx.Data["Labels"] = allLabels
|
ctx.Data["Labels"] = allLabels
|
||||||
ctx.Data["SelectLabels"] = selectLabels
|
ctx.Data["SelectLabels"] = selectLabels
|
||||||
return labelIDs
|
ret.AllLabels = allLabels
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -24,19 +24,8 @@ import (
|
|||||||
"code.gitea.io/gitea/services/context"
|
"code.gitea.io/gitea/services/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// prepareContextForCommonProfile store some common data into context data for user's profile related pages (including the nav menu)
|
// prepareContextForProfileBigAvatar set the context for big avatar view on the profile page
|
||||||
// It is designed to be fast and safe to be called multiple times in one request
|
func prepareContextForProfileBigAvatar(ctx *context.Context) {
|
||||||
func prepareContextForCommonProfile(ctx *context.Context) {
|
|
||||||
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
|
|
||||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
|
||||||
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
|
|
||||||
ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink()
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareContextForProfileBigAvatar set the context for big avatar view on the profile page
|
|
||||||
func PrepareContextForProfileBigAvatar(ctx *context.Context) {
|
|
||||||
prepareContextForCommonProfile(ctx)
|
|
||||||
|
|
||||||
ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
|
ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
|
||||||
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
|
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
|
||||||
if setting.Service.UserLocationMapURL != "" {
|
if setting.Service.UserLocationMapURL != "" {
|
||||||
@ -138,16 +127,44 @@ func FindOwnerProfileReadme(ctx *context.Context, doer *user_model.User, optProf
|
|||||||
return profileDbRepo, profileReadmeBlob
|
return profileDbRepo, profileReadmeBlob
|
||||||
}
|
}
|
||||||
|
|
||||||
func RenderUserHeader(ctx *context.Context) {
|
type PrepareOwnerHeaderResult struct {
|
||||||
prepareContextForCommonProfile(ctx)
|
ProfilePublicRepo *repo_model.Repository
|
||||||
|
ProfilePublicReadmeBlob *git.Blob
|
||||||
_, profileReadmeBlob := FindOwnerProfileReadme(ctx, ctx.Doer)
|
ProfilePrivateRepo *repo_model.Repository
|
||||||
ctx.Data["HasUserProfileReadme"] = profileReadmeBlob != nil
|
ProfilePrivateReadmeBlob *git.Blob
|
||||||
|
HasOrgProfileReadme bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadHeaderCount(ctx *context.Context) error {
|
const (
|
||||||
prepareContextForCommonProfile(ctx)
|
RepoNameProfilePrivate = ".profile-private"
|
||||||
|
RepoNameProfile = ".profile"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RenderUserOrgHeader(ctx *context.Context) (result *PrepareOwnerHeaderResult, err error) {
|
||||||
|
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
|
||||||
|
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||||
|
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
|
||||||
|
ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink()
|
||||||
|
|
||||||
|
if err := loadHeaderCount(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result = &PrepareOwnerHeaderResult{}
|
||||||
|
if ctx.ContextUser.IsOrganization() {
|
||||||
|
result.ProfilePublicRepo, result.ProfilePublicReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer)
|
||||||
|
result.ProfilePrivateRepo, result.ProfilePrivateReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer, RepoNameProfilePrivate)
|
||||||
|
result.HasOrgProfileReadme = result.ProfilePublicReadmeBlob != nil || result.ProfilePrivateReadmeBlob != nil
|
||||||
|
ctx.Data["HasOrgProfileReadme"] = result.HasOrgProfileReadme // many pages need it to show the "overview" tab
|
||||||
|
} else {
|
||||||
|
_, profileReadmeBlob := FindOwnerProfileReadme(ctx, ctx.Doer)
|
||||||
|
ctx.Data["HasUserProfileReadme"] = profileReadmeBlob != nil
|
||||||
|
prepareContextForProfileBigAvatar(ctx)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadHeaderCount(ctx *context.Context) error {
|
||||||
repoCount, err := repo_model.CountRepository(ctx, &repo_model.SearchRepoOptions{
|
repoCount, err := repo_model.CountRepository(ctx, &repo_model.SearchRepoOptions{
|
||||||
Actor: ctx.Doer,
|
Actor: ctx.Doer,
|
||||||
OwnerID: ctx.ContextUser.ID,
|
OwnerID: ctx.ContextUser.ID,
|
||||||
@ -178,29 +195,3 @@ func LoadHeaderCount(ctx *context.Context) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
RepoNameProfilePrivate = ".profile-private"
|
|
||||||
RepoNameProfile = ".profile"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PrepareOrgHeaderResult struct {
|
|
||||||
ProfilePublicRepo *repo_model.Repository
|
|
||||||
ProfilePublicReadmeBlob *git.Blob
|
|
||||||
ProfilePrivateRepo *repo_model.Repository
|
|
||||||
ProfilePrivateReadmeBlob *git.Blob
|
|
||||||
HasOrgProfileReadme bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrepareOrgHeader(ctx *context.Context) (result *PrepareOrgHeaderResult, err error) {
|
|
||||||
if err = LoadHeaderCount(ctx); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result = &PrepareOrgHeaderResult{}
|
|
||||||
result.ProfilePublicRepo, result.ProfilePublicReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer)
|
|
||||||
result.ProfilePrivateRepo, result.ProfilePrivateReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer, RepoNameProfilePrivate)
|
|
||||||
result.HasOrgProfileReadme = result.ProfilePublicReadmeBlob != nil || result.ProfilePrivateReadmeBlob != nil
|
|
||||||
ctx.Data["HasOrgProfileReadme"] = result.HasOrgProfileReadme // many pages need it to show the "overview" tab
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
@ -26,11 +26,8 @@ func CodeSearch(ctx *context.Context) {
|
|||||||
ctx.Redirect(ctx.ContextUser.HomeLink())
|
ctx.Redirect(ctx.ContextUser.HomeLink())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
shared_user.PrepareContextForProfileBigAvatar(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
shared_user.RenderUserHeader(ctx)
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
|
||||||
if err := shared_user.LoadHeaderCount(ctx); err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,10 @@ const (
|
|||||||
|
|
||||||
// ListPackages displays a list of all packages of the context user
|
// ListPackages displays a list of all packages of the context user
|
||||||
func ListPackages(ctx *context.Context) {
|
func ListPackages(ctx *context.Context) {
|
||||||
shared_user.PrepareContextForProfileBigAvatar(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
page := ctx.FormInt("page")
|
page := ctx.FormInt("page")
|
||||||
if page <= 1 {
|
if page <= 1 {
|
||||||
page = 1
|
page = 1
|
||||||
@ -94,8 +97,6 @@ func ListPackages(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_user.RenderUserHeader(ctx)
|
|
||||||
|
|
||||||
ctx.Data["Title"] = ctx.Tr("packages.title")
|
ctx.Data["Title"] = ctx.Tr("packages.title")
|
||||||
ctx.Data["IsPackagesPage"] = true
|
ctx.Data["IsPackagesPage"] = true
|
||||||
ctx.Data["Query"] = query
|
ctx.Data["Query"] = query
|
||||||
@ -106,9 +107,8 @@ func ListPackages(ctx *context.Context) {
|
|||||||
ctx.Data["Total"] = total
|
ctx.Data["Total"] = total
|
||||||
ctx.Data["RepositoryAccessMap"] = repositoryAccessMap
|
ctx.Data["RepositoryAccessMap"] = repositoryAccessMap
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,11 +126,9 @@ func ListPackages(ctx *context.Context) {
|
|||||||
ctx.Data["IsOrganizationOwner"] = false
|
ctx.Data["IsOrganizationOwner"] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
|
pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
|
||||||
pager.AddParamFromRequest(ctx.Req)
|
pager.AddParamFromRequest(ctx.Req)
|
||||||
ctx.Data["Page"] = pager
|
ctx.Data["Page"] = pager
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplPackagesList)
|
ctx.HTML(http.StatusOK, tplPackagesList)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,16 +162,17 @@ func RedirectToLastVersion(ctx *context.Context) {
|
|||||||
ctx.ServerError("GetPackageDescriptor", err)
|
ctx.ServerError("GetPackageDescriptor", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Redirect(pd.VersionWebLink())
|
ctx.Redirect(pd.VersionWebLink())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ViewPackageVersion displays a single package version
|
// ViewPackageVersion displays a single package version
|
||||||
func ViewPackageVersion(ctx *context.Context) {
|
func ViewPackageVersion(ctx *context.Context) {
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
pd := ctx.Package.Descriptor
|
pd := ctx.Package.Descriptor
|
||||||
|
|
||||||
shared_user.RenderUserHeader(ctx)
|
|
||||||
|
|
||||||
ctx.Data["Title"] = pd.Package.Name
|
ctx.Data["Title"] = pd.Package.Name
|
||||||
ctx.Data["IsPackagesPage"] = true
|
ctx.Data["IsPackagesPage"] = true
|
||||||
ctx.Data["PackageDescriptor"] = pd
|
ctx.Data["PackageDescriptor"] = pd
|
||||||
@ -301,19 +300,16 @@ func ViewPackageVersion(ctx *context.Context) {
|
|||||||
hasRepositoryAccess = permission.HasAnyUnitAccess()
|
hasRepositoryAccess = permission.HasAnyUnitAccess()
|
||||||
}
|
}
|
||||||
ctx.Data["HasRepositoryAccess"] = hasRepositoryAccess
|
ctx.Data["HasRepositoryAccess"] = hasRepositoryAccess
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplPackagesView)
|
ctx.HTML(http.StatusOK, tplPackagesView)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPackageVersions lists all versions of a package
|
// ListPackageVersions lists all versions of a package
|
||||||
func ListPackageVersions(ctx *context.Context) {
|
func ListPackageVersions(ctx *context.Context) {
|
||||||
shared_user.PrepareContextForProfileBigAvatar(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
p, err := packages_model.GetPackageByName(ctx, ctx.Package.Owner.ID, packages_model.Type(ctx.PathParam("type")), ctx.PathParam("name"))
|
p, err := packages_model.GetPackageByName(ctx, ctx.Package.Owner.ID, packages_model.Type(ctx.PathParam("type")), ctx.PathParam("name"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == packages_model.ErrPackageNotExist {
|
if err == packages_model.ErrPackageNotExist {
|
||||||
@ -336,8 +332,6 @@ func ListPackageVersions(ctx *context.Context) {
|
|||||||
query := ctx.FormTrim("q")
|
query := ctx.FormTrim("q")
|
||||||
sort := ctx.FormTrim("sort")
|
sort := ctx.FormTrim("sort")
|
||||||
|
|
||||||
shared_user.RenderUserHeader(ctx)
|
|
||||||
|
|
||||||
ctx.Data["Title"] = ctx.Tr("packages.title")
|
ctx.Data["Title"] = ctx.Tr("packages.title")
|
||||||
ctx.Data["IsPackagesPage"] = true
|
ctx.Data["IsPackagesPage"] = true
|
||||||
ctx.Data["PackageDescriptor"] = &packages_model.PackageDescriptor{
|
ctx.Data["PackageDescriptor"] = &packages_model.PackageDescriptor{
|
||||||
@ -393,12 +387,6 @@ func ListPackageVersions(ctx *context.Context) {
|
|||||||
|
|
||||||
ctx.Data["Total"] = total
|
ctx.Data["Total"] = total
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
|
pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
|
||||||
pager.AddParamFromRequest(ctx.Req)
|
pager.AddParamFromRequest(ctx.Req)
|
||||||
ctx.Data["Page"] = pager
|
ctx.Data["Page"] = pager
|
||||||
@ -410,7 +398,10 @@ func ListPackageVersions(ctx *context.Context) {
|
|||||||
func PackageSettings(ctx *context.Context) {
|
func PackageSettings(ctx *context.Context) {
|
||||||
pd := ctx.Package.Descriptor
|
pd := ctx.Package.Descriptor
|
||||||
|
|
||||||
shared_user.RenderUserHeader(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["Title"] = pd.Package.Name
|
ctx.Data["Title"] = pd.Package.Name
|
||||||
ctx.Data["IsPackagesPage"] = true
|
ctx.Data["IsPackagesPage"] = true
|
||||||
@ -423,12 +414,6 @@ func PackageSettings(ctx *context.Context) {
|
|||||||
ctx.Data["Repos"] = repos
|
ctx.Data["Repos"] = repos
|
||||||
ctx.Data["CanWritePackages"] = ctx.Package.AccessMode >= perm.AccessModeWrite || ctx.IsUserSiteAdmin()
|
ctx.Data["CanWritePackages"] = ctx.Package.AccessMode >= perm.AccessModeWrite || ctx.IsUserSiteAdmin()
|
||||||
|
|
||||||
err := shared_user.LoadHeaderCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplPackagesSettings)
|
ctx.HTML(http.StatusOK, tplPackagesSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +78,15 @@ func userProfile(ctx *context.Context) {
|
|||||||
|
|
||||||
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
|
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
|
||||||
prepareUserProfileTabData(ctx, showPrivate, profileDbRepo, profileReadmeBlob)
|
prepareUserProfileTabData(ctx, showPrivate, profileDbRepo, profileReadmeBlob)
|
||||||
// call PrepareContextForProfileBigAvatar later to avoid re-querying the NumFollowers & NumFollowing
|
|
||||||
shared_user.PrepareContextForProfileBigAvatar(ctx)
|
// prepare the user nav header data after "prepareUserProfileTabData" to avoid re-querying the NumFollowers & NumFollowing
|
||||||
|
// because ctx.Data["NumFollowers"] and "NumFollowing" logic duplicates in both of them
|
||||||
|
// and the "profile readme" related logic also duplicates in both of FindOwnerProfileReadme and RenderUserOrgHeader
|
||||||
|
// TODO: it is a bad design and should be refactored later,
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.HTML(http.StatusOK, tplProfile)
|
ctx.HTML(http.StatusOK, tplProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,9 +309,8 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb
|
|||||||
ctx.Data["Repos"] = repos
|
ctx.Data["Repos"] = repos
|
||||||
ctx.Data["Total"] = total
|
ctx.Data["Total"] = total
|
||||||
|
|
||||||
err = shared_user.LoadHeaderCount(ctx)
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
if err != nil {
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,9 +334,11 @@ func ActionUserFollow(ctx *context.Context) {
|
|||||||
ctx.HTTPError(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action")))
|
ctx.HTTPError(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
if ctx.ContextUser.IsIndividual() {
|
if ctx.ContextUser.IsIndividual() {
|
||||||
shared_user.PrepareContextForProfileBigAvatar(ctx)
|
|
||||||
ctx.HTML(http.StatusOK, tplProfileBigAvatar)
|
ctx.HTML(http.StatusOK, tplProfileBigAvatar)
|
||||||
return
|
return
|
||||||
} else if ctx.ContextUser.IsOrganization() {
|
} else if ctx.ContextUser.IsOrganization() {
|
||||||
|
@ -43,8 +43,9 @@ func ApplicationsPost(ctx *context.Context) {
|
|||||||
|
|
||||||
_ = ctx.Req.ParseForm()
|
_ = ctx.Req.ParseForm()
|
||||||
var scopeNames []string
|
var scopeNames []string
|
||||||
|
const accessTokenScopePrefix = "scope-"
|
||||||
for k, v := range ctx.Req.Form {
|
for k, v := range ctx.Req.Form {
|
||||||
if strings.HasPrefix(k, "scope-") {
|
if strings.HasPrefix(k, accessTokenScopePrefix) {
|
||||||
scopeNames = append(scopeNames, v...)
|
scopeNames = append(scopeNames, v...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,8 @@ func (oa *OAuth2CommonHandlers) renderEditPage(ctx *context.Context) {
|
|||||||
ctx.Data["FormActionPath"] = fmt.Sprintf("%s/%d", oa.BasePathEditPrefix, app.ID)
|
ctx.Data["FormActionPath"] = fmt.Sprintf("%s/%d", oa.BasePathEditPrefix, app.ID)
|
||||||
|
|
||||||
if ctx.ContextUser != nil && ctx.ContextUser.IsOrganization() {
|
if ctx.ContextUser != nil && ctx.ContextUser.IsOrganization() {
|
||||||
if err := shared_user.LoadHeaderCount(ctx); err != nil {
|
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||||
ctx.ServerError("LoadHeaderCount", err)
|
ctx.ServerError("RenderUserOrgHeader", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,12 +519,13 @@ func (f *CreateMilestoneForm) Validate(req *http.Request, errs binding.Errors) b
|
|||||||
|
|
||||||
// CreateLabelForm form for creating label
|
// CreateLabelForm form for creating label
|
||||||
type CreateLabelForm struct {
|
type CreateLabelForm struct {
|
||||||
ID int64
|
ID int64
|
||||||
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_title"`
|
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_title"`
|
||||||
Exclusive bool `form:"exclusive"`
|
Exclusive bool `form:"exclusive"`
|
||||||
IsArchived bool `form:"is_archived"`
|
ExclusiveOrder int `form:"exclusive_order"`
|
||||||
Description string `binding:"MaxSize(200)" locale:"repo.issues.label_description"`
|
IsArchived bool `form:"is_archived"`
|
||||||
Color string `binding:"Required;MaxSize(7)" locale:"repo.issues.label_color"`
|
Description string `binding:"MaxSize(200)" locale:"repo.issues.label_description"`
|
||||||
|
Color string `binding:"Required;MaxSize(7)" locale:"repo.issues.label_color"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .IsOrganizationOwner}}
|
{{if and EnableTimetracking .IsOrganizationOwner}}
|
||||||
<a class="{{if $.PageIsOrgTimes}}active{{end}} item" href="{{$.OrgLink}}/worktime">
|
<a class="{{if $.PageIsOrgTimes}}active{{end}} item" href="{{$.OrgLink}}/worktime">
|
||||||
{{svg "octicon-clock"}} {{ctx.Locale.Tr "org.worktime"}}
|
{{svg "octicon-clock"}} {{ctx.Locale.Tr "org.worktime"}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,9 +1,24 @@
|
|||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div role="main" aria-label="{{.Title}}" class="page-content organization projects edit-project new">
|
{{if .ContextUser.IsOrganization}}
|
||||||
{{template "shared/user/org_profile_avatar" .}}
|
<div role="main" aria-label="{{.Title}}" class="page-content organization projects">
|
||||||
|
{{template "org/header" .}}
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
{{template "user/overview/header" .}}
|
{{template "projects/new" .}}
|
||||||
{{template "projects/new" .}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div role="main" aria-label="{{.Title}}" class="page-content user profile">
|
||||||
|
<div class="ui container">
|
||||||
|
<div class="ui stackable grid">
|
||||||
|
<div class="ui four wide column">
|
||||||
|
{{template "shared/user/profile_big_avatar" .}}
|
||||||
|
</div>
|
||||||
|
<div class="ui twelve wide column tw-mb-4">
|
||||||
|
{{template "user/overview/header" .}}
|
||||||
|
{{template "projects/new" .}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
||||||
|
106
templates/package/shared/view.tmpl
Normal file
106
templates/package/shared/view.tmpl
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<div class="issue-title-header">
|
||||||
|
<h1>{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</h1>
|
||||||
|
<div>
|
||||||
|
{{$timeStr := DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}
|
||||||
|
{{if .HasRepositoryAccess}}
|
||||||
|
{{ctx.Locale.Tr "packages.published_by_in" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName .PackageDescriptor.Repository.Link .PackageDescriptor.Repository.FullName}}
|
||||||
|
{{else}}
|
||||||
|
{{ctx.Locale.Tr "packages.published_by" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="issue-content">
|
||||||
|
<div class="issue-content-left">
|
||||||
|
{{template "package/content/alpine" .}}
|
||||||
|
{{template "package/content/arch" .}}
|
||||||
|
{{template "package/content/cargo" .}}
|
||||||
|
{{template "package/content/chef" .}}
|
||||||
|
{{template "package/content/composer" .}}
|
||||||
|
{{template "package/content/conan" .}}
|
||||||
|
{{template "package/content/conda" .}}
|
||||||
|
{{template "package/content/container" .}}
|
||||||
|
{{template "package/content/cran" .}}
|
||||||
|
{{template "package/content/debian" .}}
|
||||||
|
{{template "package/content/generic" .}}
|
||||||
|
{{template "package/content/go" .}}
|
||||||
|
{{template "package/content/helm" .}}
|
||||||
|
{{template "package/content/maven" .}}
|
||||||
|
{{template "package/content/npm" .}}
|
||||||
|
{{template "package/content/nuget" .}}
|
||||||
|
{{template "package/content/pub" .}}
|
||||||
|
{{template "package/content/pypi" .}}
|
||||||
|
{{template "package/content/rpm" .}}
|
||||||
|
{{template "package/content/rubygems" .}}
|
||||||
|
{{template "package/content/swift" .}}
|
||||||
|
{{template "package/content/vagrant" .}}
|
||||||
|
</div>
|
||||||
|
<div class="issue-content-right ui segment">
|
||||||
|
<strong>{{ctx.Locale.Tr "packages.details"}}</strong>
|
||||||
|
<div class="ui relaxed list flex-items-block">
|
||||||
|
<div class="item">{{svg .PackageDescriptor.Package.Type.SVGName}} {{.PackageDescriptor.Package.Type.Name}}</div>
|
||||||
|
{{if .HasRepositoryAccess}}
|
||||||
|
<div class="item">{{svg "octicon-repo"}} <a href="{{.PackageDescriptor.Repository.Link}}">{{.PackageDescriptor.Repository.FullName}}</a></div>
|
||||||
|
{{end}}
|
||||||
|
<div class="item">{{svg "octicon-calendar"}} {{DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}</div>
|
||||||
|
<div class="item">{{svg "octicon-download"}} {{.PackageDescriptor.Version.DownloadCount}}</div>
|
||||||
|
{{template "package/metadata/alpine" .}}
|
||||||
|
{{template "package/metadata/arch" .}}
|
||||||
|
{{template "package/metadata/cargo" .}}
|
||||||
|
{{template "package/metadata/chef" .}}
|
||||||
|
{{template "package/metadata/composer" .}}
|
||||||
|
{{template "package/metadata/conan" .}}
|
||||||
|
{{template "package/metadata/conda" .}}
|
||||||
|
{{template "package/metadata/container" .}}
|
||||||
|
{{template "package/metadata/cran" .}}
|
||||||
|
{{template "package/metadata/debian" .}}
|
||||||
|
{{template "package/metadata/generic" .}}
|
||||||
|
{{template "package/metadata/helm" .}}
|
||||||
|
{{template "package/metadata/maven" .}}
|
||||||
|
{{template "package/metadata/npm" .}}
|
||||||
|
{{template "package/metadata/nuget" .}}
|
||||||
|
{{template "package/metadata/pub" .}}
|
||||||
|
{{template "package/metadata/pypi" .}}
|
||||||
|
{{template "package/metadata/rpm" .}}
|
||||||
|
{{template "package/metadata/rubygems" .}}
|
||||||
|
{{template "package/metadata/swift" .}}
|
||||||
|
{{template "package/metadata/vagrant" .}}
|
||||||
|
{{if not (and (eq .PackageDescriptor.Package.Type "container") .PackageDescriptor.Metadata.Manifests)}}
|
||||||
|
<div class="item">{{svg "octicon-database"}} {{FileSize .PackageDescriptor.CalculateBlobSize}}</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{if not (eq .PackageDescriptor.Package.Type "container")}}
|
||||||
|
<div class="divider"></div>
|
||||||
|
<strong>{{ctx.Locale.Tr "packages.assets"}} ({{len .PackageDescriptor.Files}})</strong>
|
||||||
|
<div class="ui relaxed list">
|
||||||
|
{{range .PackageDescriptor.Files}}
|
||||||
|
<div class="item">
|
||||||
|
<a href="{{$.Link}}/files/{{.File.ID}}">{{.File.Name}}</a>
|
||||||
|
<span class="text small file-size">{{FileSize .Blob.Size}}</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<div class="divider"></div>
|
||||||
|
<strong>{{ctx.Locale.Tr "packages.versions"}} ({{.TotalVersionCount}})</strong>
|
||||||
|
<a class="tw-float-right" href="{{$.PackageDescriptor.PackageWebLink}}/versions">{{ctx.Locale.Tr "packages.versions.view_all"}}</a>
|
||||||
|
<div class="ui relaxed list">
|
||||||
|
{{range .LatestVersions}}
|
||||||
|
<div class="item tw-flex">
|
||||||
|
<a class="tw-flex-1 gt-ellipsis" title="{{.Version}}" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
|
||||||
|
<span class="text small">{{DateUtils.AbsoluteShort .CreatedUnix}}</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{if or .CanWritePackages .HasRepositoryAccess}}
|
||||||
|
<div class="divider"></div>
|
||||||
|
<div class="ui relaxed list flex-items-block">
|
||||||
|
{{if .HasRepositoryAccess}}
|
||||||
|
<div class="item">{{svg "octicon-issue-opened"}} <a href="{{.PackageDescriptor.Repository.Link}}/issues">{{ctx.Locale.Tr "repo.issues"}}</a></div>
|
||||||
|
{{end}}
|
||||||
|
{{if .CanWritePackages}}
|
||||||
|
<div class="item">{{svg "octicon-tools"}} <a href="{{.Link}}/settings">{{ctx.Locale.Tr "repo.settings"}}</a></div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,114 +1,24 @@
|
|||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div role="main" aria-label="{{.Title}}" class="page-content repository packages">
|
{{if .ContextUser.IsOrganization}}
|
||||||
{{template "shared/user/org_profile_avatar" .}}
|
<div role="main" aria-label="{{.Title}}" class="page-content organization packages">
|
||||||
|
{{template "org/header" .}}
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
{{template "user/overview/header" .}}
|
{{template "package/shared/view" .}}
|
||||||
<div class="issue-title-header">
|
</div>
|
||||||
<h1>{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</h1>
|
</div>
|
||||||
<div>
|
{{else}}
|
||||||
{{$timeStr := DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}
|
<div role="main" aria-label="{{.Title}}" class="page-content user profile packages">
|
||||||
{{if .HasRepositoryAccess}}
|
<div class="ui container">
|
||||||
{{ctx.Locale.Tr "packages.published_by_in" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName .PackageDescriptor.Repository.Link .PackageDescriptor.Repository.FullName}}
|
<div class="ui stackable grid">
|
||||||
{{else}}
|
<div class="ui four wide column">
|
||||||
{{ctx.Locale.Tr "packages.published_by" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName}}
|
{{template "shared/user/profile_big_avatar" .}}
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="ui twelve wide column tw-mb-4">
|
||||||
<div class="issue-content">
|
{{template "user/overview/header" .}}
|
||||||
<div class="issue-content-left">
|
{{template "package/shared/view" .}}
|
||||||
{{template "package/content/alpine" .}}
|
|
||||||
{{template "package/content/arch" .}}
|
|
||||||
{{template "package/content/cargo" .}}
|
|
||||||
{{template "package/content/chef" .}}
|
|
||||||
{{template "package/content/composer" .}}
|
|
||||||
{{template "package/content/conan" .}}
|
|
||||||
{{template "package/content/conda" .}}
|
|
||||||
{{template "package/content/container" .}}
|
|
||||||
{{template "package/content/cran" .}}
|
|
||||||
{{template "package/content/debian" .}}
|
|
||||||
{{template "package/content/generic" .}}
|
|
||||||
{{template "package/content/go" .}}
|
|
||||||
{{template "package/content/helm" .}}
|
|
||||||
{{template "package/content/maven" .}}
|
|
||||||
{{template "package/content/npm" .}}
|
|
||||||
{{template "package/content/nuget" .}}
|
|
||||||
{{template "package/content/pub" .}}
|
|
||||||
{{template "package/content/pypi" .}}
|
|
||||||
{{template "package/content/rpm" .}}
|
|
||||||
{{template "package/content/rubygems" .}}
|
|
||||||
{{template "package/content/swift" .}}
|
|
||||||
{{template "package/content/vagrant" .}}
|
|
||||||
</div>
|
|
||||||
<div class="issue-content-right ui segment">
|
|
||||||
<strong>{{ctx.Locale.Tr "packages.details"}}</strong>
|
|
||||||
<div class="ui relaxed list flex-items-block">
|
|
||||||
<div class="item">{{svg .PackageDescriptor.Package.Type.SVGName}} {{.PackageDescriptor.Package.Type.Name}}</div>
|
|
||||||
{{if .HasRepositoryAccess}}
|
|
||||||
<div class="item">{{svg "octicon-repo"}} <a href="{{.PackageDescriptor.Repository.Link}}">{{.PackageDescriptor.Repository.FullName}}</a></div>
|
|
||||||
{{end}}
|
|
||||||
<div class="item">{{svg "octicon-calendar"}} {{DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}</div>
|
|
||||||
<div class="item">{{svg "octicon-download"}} {{.PackageDescriptor.Version.DownloadCount}}</div>
|
|
||||||
{{template "package/metadata/alpine" .}}
|
|
||||||
{{template "package/metadata/arch" .}}
|
|
||||||
{{template "package/metadata/cargo" .}}
|
|
||||||
{{template "package/metadata/chef" .}}
|
|
||||||
{{template "package/metadata/composer" .}}
|
|
||||||
{{template "package/metadata/conan" .}}
|
|
||||||
{{template "package/metadata/conda" .}}
|
|
||||||
{{template "package/metadata/container" .}}
|
|
||||||
{{template "package/metadata/cran" .}}
|
|
||||||
{{template "package/metadata/debian" .}}
|
|
||||||
{{template "package/metadata/generic" .}}
|
|
||||||
{{template "package/metadata/helm" .}}
|
|
||||||
{{template "package/metadata/maven" .}}
|
|
||||||
{{template "package/metadata/npm" .}}
|
|
||||||
{{template "package/metadata/nuget" .}}
|
|
||||||
{{template "package/metadata/pub" .}}
|
|
||||||
{{template "package/metadata/pypi" .}}
|
|
||||||
{{template "package/metadata/rpm" .}}
|
|
||||||
{{template "package/metadata/rubygems" .}}
|
|
||||||
{{template "package/metadata/swift" .}}
|
|
||||||
{{template "package/metadata/vagrant" .}}
|
|
||||||
{{if not (and (eq .PackageDescriptor.Package.Type "container") .PackageDescriptor.Metadata.Manifests)}}
|
|
||||||
<div class="item">{{svg "octicon-database"}} {{FileSize .PackageDescriptor.CalculateBlobSize}}</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{if not (eq .PackageDescriptor.Package.Type "container")}}
|
|
||||||
<div class="divider"></div>
|
|
||||||
<strong>{{ctx.Locale.Tr "packages.assets"}} ({{len .PackageDescriptor.Files}})</strong>
|
|
||||||
<div class="ui relaxed list">
|
|
||||||
{{range .PackageDescriptor.Files}}
|
|
||||||
<div class="item">
|
|
||||||
<a href="{{$.Link}}/files/{{.File.ID}}">{{.File.Name}}</a>
|
|
||||||
<span class="text small file-size">{{FileSize .Blob.Size}}</span>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
<div class="divider"></div>
|
|
||||||
<strong>{{ctx.Locale.Tr "packages.versions"}} ({{.TotalVersionCount}})</strong>
|
|
||||||
<a class="tw-float-right" href="{{$.PackageDescriptor.PackageWebLink}}/versions">{{ctx.Locale.Tr "packages.versions.view_all"}}</a>
|
|
||||||
<div class="ui relaxed list">
|
|
||||||
{{range .LatestVersions}}
|
|
||||||
<div class="item tw-flex">
|
|
||||||
<a class="tw-flex-1 gt-ellipsis" title="{{.Version}}" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
|
|
||||||
<span class="text small">{{DateUtils.AbsoluteShort .CreatedUnix}}</span>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{if or .CanWritePackages .HasRepositoryAccess}}
|
|
||||||
<div class="divider"></div>
|
|
||||||
<div class="ui relaxed list flex-items-block">
|
|
||||||
{{if .HasRepositoryAccess}}
|
|
||||||
<div class="item">{{svg "octicon-issue-opened"}} <a href="{{.PackageDescriptor.Repository.Link}}/issues">{{ctx.Locale.Tr "repo.issues"}}</a></div>
|
|
||||||
{{end}}
|
|
||||||
{{if .CanWritePackages}}
|
|
||||||
<div class="item">{{svg "octicon-tools"}} <a href="{{.Link}}/settings">{{ctx.Locale.Tr "repo.settings"}}</a></div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
||||||
|
@ -133,5 +133,11 @@
|
|||||||
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "leastcomment"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
|
<a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "leastcomment"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
|
||||||
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "nearduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
|
<a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "nearduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
|
||||||
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "farduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
|
<a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="{{QueryBuild $queryLink "sort" "farduedate"}}">{{ctx.Locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
|
||||||
|
<div class="divider"></div>
|
||||||
|
<div class="header">{{ctx.Locale.Tr "repo.issues.filter_label"}}</div>
|
||||||
|
{{range $scope := .ExclusiveLabelScopes}}
|
||||||
|
{{$sortType := (printf "scope-%s" $scope)}}
|
||||||
|
<a class="{{if eq $.SortType $sortType}}active {{end}}item" href="{{QueryBuild $queryLink "sort" $sortType}}">{{$scope}}</a>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,7 +24,13 @@
|
|||||||
<div class="desc tw-ml-1 tw-mt-2 tw-hidden label-exclusive-warning">
|
<div class="desc tw-ml-1 tw-mt-2 tw-hidden label-exclusive-warning">
|
||||||
{{svg "octicon-alert"}} {{ctx.Locale.Tr "repo.issues.label_exclusive_warning"}}
|
{{svg "octicon-alert"}} {{ctx.Locale.Tr "repo.issues.label_exclusive_warning"}}
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<div class="field label-exclusive-order-input-field tw-mt-2">
|
||||||
|
<label class="flex-text-block">
|
||||||
|
{{ctx.Locale.Tr "repo.issues.label_exclusive_order"}}
|
||||||
|
<span data-tooltip-content="{{ctx.Locale.Tr "repo.issues.label_exclusive_order_tooltip"}}">{{svg "octicon-info"}}</span>
|
||||||
|
</label>
|
||||||
|
<input class="label-exclusive-order-input" name="exclusive_order" type="number" maxlength="4">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field label-is-archived-input-field">
|
<div class="field label-is-archived-input-field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
data-label-id="{{.ID}}" data-label-name="{{.Name}}" data-label-color="{{.Color}}"
|
data-label-id="{{.ID}}" data-label-name="{{.Name}}" data-label-color="{{.Color}}"
|
||||||
data-label-exclusive="{{.Exclusive}}" data-label-is-archived="{{gt .ArchivedUnix 0}}"
|
data-label-exclusive="{{.Exclusive}}" data-label-is-archived="{{gt .ArchivedUnix 0}}"
|
||||||
data-label-num-issues="{{.NumIssues}}" data-label-description="{{.Description}}"
|
data-label-num-issues="{{.NumIssues}}" data-label-description="{{.Description}}"
|
||||||
|
data-label-exclusive-order="{{.ExclusiveOrder}}"
|
||||||
>{{svg "octicon-pencil"}} {{ctx.Locale.Tr "repo.issues.label_edit"}}</a>
|
>{{svg "octicon-pencil"}} {{ctx.Locale.Tr "repo.issues.label_edit"}}</a>
|
||||||
<a class="link-action" href="#" data-url="{{$.Link}}/delete?id={{.ID}}"
|
<a class="link-action" href="#" data-url="{{$.Link}}/delete?id={{.ID}}"
|
||||||
data-modal-confirm-header="{{ctx.Locale.Tr "repo.issues.label_deletion"}}"
|
data-modal-confirm-header="{{ctx.Locale.Tr "repo.issues.label_deletion"}}"
|
||||||
|
@ -1127,6 +1127,7 @@ table th[data-sortt-desc] .svg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ui.list.flex-items-block > .item,
|
.ui.list.flex-items-block > .item,
|
||||||
|
.ui.form .field > label.flex-text-block, /* override fomantic "block" style */
|
||||||
.flex-items-block > .item,
|
.flex-items-block > .item,
|
||||||
.flex-text-block {
|
.flex-text-block {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1604,6 +1604,12 @@ td .commit-summary {
|
|||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.label.scope-middle {
|
||||||
|
border-radius: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.ui.label.scope-right {
|
.ui.label.scope-right {
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
|
@ -18,6 +18,8 @@ export function initCompLabelEdit(pageSelector: string) {
|
|||||||
const elExclusiveField = elModal.querySelector('.label-exclusive-input-field');
|
const elExclusiveField = elModal.querySelector('.label-exclusive-input-field');
|
||||||
const elExclusiveInput = elModal.querySelector<HTMLInputElement>('.label-exclusive-input');
|
const elExclusiveInput = elModal.querySelector<HTMLInputElement>('.label-exclusive-input');
|
||||||
const elExclusiveWarning = elModal.querySelector('.label-exclusive-warning');
|
const elExclusiveWarning = elModal.querySelector('.label-exclusive-warning');
|
||||||
|
const elExclusiveOrderField = elModal.querySelector<HTMLInputElement>('.label-exclusive-order-input-field');
|
||||||
|
const elExclusiveOrderInput = elModal.querySelector<HTMLInputElement>('.label-exclusive-order-input');
|
||||||
const elIsArchivedField = elModal.querySelector('.label-is-archived-input-field');
|
const elIsArchivedField = elModal.querySelector('.label-is-archived-input-field');
|
||||||
const elIsArchivedInput = elModal.querySelector<HTMLInputElement>('.label-is-archived-input');
|
const elIsArchivedInput = elModal.querySelector<HTMLInputElement>('.label-is-archived-input');
|
||||||
const elDescInput = elModal.querySelector<HTMLInputElement>('.label-desc-input');
|
const elDescInput = elModal.querySelector<HTMLInputElement>('.label-desc-input');
|
||||||
@ -29,6 +31,13 @@ export function initCompLabelEdit(pageSelector: string) {
|
|||||||
const showExclusiveWarning = hasScope && elExclusiveInput.checked && elModal.hasAttribute('data-need-warn-exclusive');
|
const showExclusiveWarning = hasScope && elExclusiveInput.checked && elModal.hasAttribute('data-need-warn-exclusive');
|
||||||
toggleElem(elExclusiveWarning, showExclusiveWarning);
|
toggleElem(elExclusiveWarning, showExclusiveWarning);
|
||||||
if (!hasScope) elExclusiveInput.checked = false;
|
if (!hasScope) elExclusiveInput.checked = false;
|
||||||
|
toggleElem(elExclusiveOrderField, elExclusiveInput.checked);
|
||||||
|
|
||||||
|
if (parseInt(elExclusiveOrderInput.value) <= 0) {
|
||||||
|
elExclusiveOrderInput.style.color = 'var(--color-placeholder-text) !important';
|
||||||
|
} else {
|
||||||
|
elExclusiveOrderInput.style.color = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showLabelEditModal = (btn:HTMLElement) => {
|
const showLabelEditModal = (btn:HTMLElement) => {
|
||||||
@ -36,6 +45,7 @@ export function initCompLabelEdit(pageSelector: string) {
|
|||||||
const form = elModal.querySelector<HTMLFormElement>('form');
|
const form = elModal.querySelector<HTMLFormElement>('form');
|
||||||
elLabelId.value = btn.getAttribute('data-label-id') || '';
|
elLabelId.value = btn.getAttribute('data-label-id') || '';
|
||||||
elNameInput.value = btn.getAttribute('data-label-name') || '';
|
elNameInput.value = btn.getAttribute('data-label-name') || '';
|
||||||
|
elExclusiveOrderInput.value = btn.getAttribute('data-label-exclusive-order') || '0';
|
||||||
elIsArchivedInput.checked = btn.getAttribute('data-label-is-archived') === 'true';
|
elIsArchivedInput.checked = btn.getAttribute('data-label-is-archived') === 'true';
|
||||||
elExclusiveInput.checked = btn.getAttribute('data-label-exclusive') === 'true';
|
elExclusiveInput.checked = btn.getAttribute('data-label-exclusive') === 'true';
|
||||||
elDescInput.value = btn.getAttribute('data-label-description') || '';
|
elDescInput.value = btn.getAttribute('data-label-description') || '';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user