mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-18 00:01:32 -04:00
Compare commits
No commits in common. "a8e13e64da7f9dc6176365e6b9295981af5d81ea" and "023521b016d004ca185f0c4e2d80d30e2722fa81" have entirely different histories.
a8e13e64da
...
023521b016
@ -23,15 +23,17 @@ For repositories, labels can be created by going to `Issues` and clicking on `La
|
||||
|
||||
For organizations, you can define organization-wide labels that are shared with all organization repositories, including both already-existing repositories as well as newly created ones. Organization-wide labels can be created in the organization `Settings`.
|
||||
|
||||
Labels have a mandatory name, a mandatory color, an optional description, and must either be exclusive or not (see `Scoped Labels` below).
|
||||
Labels have a mandatory name, a mandatory color, an optional description, and must either be exclusive or not (see `Scoped labels` below).
|
||||
|
||||
When you create a repository, you can ensure certain labels exist by using the `Issue Labels` option. This option lists a number of available label sets that are [configured globally on your instance](../customizing-gitea/#labels). Its contained labels will all be created as well while creating the repository.
|
||||
|
||||
## Scoped Labels
|
||||
|
||||
Scoped labels are used to ensure at most a single label with the same scope is assigned to an issue or pull request. For example, if labels `kind/bug` and `kind/enhancement` have the Exclusive option set, an issue can only be classified as a bug or an enhancement.
|
||||
A scoped label is a label that contains `/` in its name (not at either end of the name). For example labels `kind/bug` and `kind/enhancement` both have scope `kind`. Such labels will display the scope with slightly darker color.
|
||||
|
||||
A scoped label must contain `/` in its name (not at either end of the name). The scope of a label is determined based on the **last** `/`, so for example the scope of label `scope/subscope/item` is `scope/subscope`.
|
||||
The scope of a label is determined based on the **last** `/`, so for example the scope of label `scope/subscope/item` is `scope/subscope`.
|
||||
|
||||
Scoped labels can be marked as exclusive. This ensures at most a single label with the same scope is assigned to an issue or pull request. For example, if `kind/bug` and `kind/enhancement` are marked exclusive, an issue can only be classified as a bug or an enhancement.
|
||||
|
||||
## Filtering by Label
|
||||
|
||||
|
@ -834,7 +834,7 @@ func RenderLabel(ctx context.Context, label *issues_model.Label) string {
|
||||
// Make scope and item background colors slightly darker and lighter respectively.
|
||||
// More contrast needed with higher luminance, empirically tweaked.
|
||||
luminance := (0.299*r + 0.587*g + 0.114*b) / 255
|
||||
contrast := 0.01 + luminance*0.03
|
||||
contrast := 0.01 + luminance*0.06
|
||||
// Ensure we add the same amount of contrast also near 0 and 1.
|
||||
darken := contrast + math.Max(luminance+contrast-1.0, 0.0)
|
||||
lighten := contrast + math.Max(contrast-luminance, 0.0)
|
||||
@ -859,10 +859,12 @@ func RenderLabel(ctx context.Context, label *issues_model.Label) string {
|
||||
|
||||
return fmt.Sprintf("<span class='ui label scope-parent' 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='background: linear-gradient(-80deg, %s 48%%, %s 52%% 0%%);'> </div>"+
|
||||
"<div class='ui label scope-right' style='color: %s !important; background-color: %s !important''>%s</div>"+
|
||||
"</span>",
|
||||
description,
|
||||
textColor, scopeColor, scopeText,
|
||||
itemColor, scopeColor,
|
||||
textColor, itemColor, itemText)
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ func CreateIssueAttachment(ctx *context.APIContext) {
|
||||
filename = query
|
||||
}
|
||||
|
||||
attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{
|
||||
attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, &repo_model.Attachment{
|
||||
Name: filename,
|
||||
UploaderID: ctx.Doer.ID,
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
|
@ -180,7 +180,7 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) {
|
||||
filename = query
|
||||
}
|
||||
|
||||
attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{
|
||||
attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, &repo_model.Attachment{
|
||||
Name: filename,
|
||||
UploaderID: ctx.Doer.ID,
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
|
@ -194,7 +194,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
// Create a new attachment and save the file
|
||||
attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{
|
||||
attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, &repo_model.Attachment{
|
||||
Name: filename,
|
||||
UploaderID: ctx.Doer.ID,
|
||||
RepoID: release.RepoID,
|
||||
|
@ -44,7 +44,7 @@ func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
attach, err := attachment.UploadAttachment(file, allowedTypes, header.Size, &repo_model.Attachment{
|
||||
attach, err := attachment.UploadAttachment(file, allowedTypes, &repo_model.Attachment{
|
||||
Name: header.Filename,
|
||||
UploaderID: ctx.Doer.ID,
|
||||
RepoID: repoID,
|
||||
|
@ -113,7 +113,7 @@ func Projects(ctx *context.Context) {
|
||||
pager.AddParam(ctx, "state", "State")
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
|
||||
ctx.Data["CanWriteProjects"] = true
|
||||
ctx.Data["IsShowClosed"] = isShowClosed
|
||||
ctx.Data["IsProjectsPage"] = true
|
||||
ctx.Data["SortType"] = sortType
|
||||
|
@ -19,14 +19,14 @@ import (
|
||||
)
|
||||
|
||||
// NewAttachment creates a new attachment object, but do not verify.
|
||||
func NewAttachment(attach *repo_model.Attachment, file io.Reader, size int64) (*repo_model.Attachment, error) {
|
||||
func NewAttachment(attach *repo_model.Attachment, file io.Reader) (*repo_model.Attachment, error) {
|
||||
if attach.RepoID == 0 {
|
||||
return nil, fmt.Errorf("attachment %s should belong to a repository", attach.Name)
|
||||
}
|
||||
|
||||
err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||
attach.UUID = uuid.New().String()
|
||||
size, err := storage.Attachments.Save(attach.RelativePath(), file, size)
|
||||
size, err := storage.Attachments.Save(attach.RelativePath(), file, -1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Create: %w", err)
|
||||
}
|
||||
@ -39,7 +39,7 @@ func NewAttachment(attach *repo_model.Attachment, file io.Reader, size int64) (*
|
||||
}
|
||||
|
||||
// UploadAttachment upload new attachment into storage and update database
|
||||
func UploadAttachment(file io.Reader, allowedTypes string, fileSize int64, opts *repo_model.Attachment) (*repo_model.Attachment, error) {
|
||||
func UploadAttachment(file io.Reader, allowedTypes string, opts *repo_model.Attachment) (*repo_model.Attachment, error) {
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := util.ReadAtMost(file, buf)
|
||||
buf = buf[:n]
|
||||
@ -48,5 +48,5 @@ func UploadAttachment(file io.Reader, allowedTypes string, fileSize int64, opts
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewAttachment(opts, io.MultiReader(bytes.NewReader(buf), file), fileSize)
|
||||
return NewAttachment(opts, io.MultiReader(bytes.NewReader(buf), file))
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ func TestUploadAttachment(t *testing.T) {
|
||||
RepoID: 1,
|
||||
UploaderID: user.ID,
|
||||
Name: filepath.Base(fPath),
|
||||
}, f, -1)
|
||||
}, f)
|
||||
assert.NoError(t, err)
|
||||
|
||||
attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, attach.UUID)
|
||||
|
@ -87,7 +87,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u
|
||||
attachmentIDs := make([]string, 0, len(content.Attachments))
|
||||
if setting.Attachment.Enabled {
|
||||
for _, attachment := range content.Attachments {
|
||||
a, err := attachment_service.UploadAttachment(bytes.NewReader(attachment.Content), setting.Attachment.AllowedTypes, int64(len(attachment.Content)), &repo_model.Attachment{
|
||||
a, err := attachment_service.UploadAttachment(bytes.NewReader(attachment.Content), setting.Attachment.AllowedTypes, &repo_model.Attachment{
|
||||
Name: attachment.Name,
|
||||
UploaderID: doer.ID,
|
||||
RepoID: issue.Repo.ID,
|
||||
|
@ -106,13 +106,11 @@ func TestRelease_Create(t *testing.T) {
|
||||
IsTag: false,
|
||||
}, nil, ""))
|
||||
|
||||
testPlayload := "testtest"
|
||||
|
||||
attach, err := attachment.NewAttachment(&repo_model.Attachment{
|
||||
RepoID: repo.ID,
|
||||
UploaderID: user.ID,
|
||||
Name: "test.txt",
|
||||
}, strings.NewReader(testPlayload), int64(len([]byte(testPlayload))))
|
||||
}, strings.NewReader("testtest"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
release := repo_model.Release{
|
||||
@ -241,12 +239,11 @@ func TestRelease_Update(t *testing.T) {
|
||||
assert.Equal(t, tagName, release.TagName)
|
||||
|
||||
// Add new attachments
|
||||
samplePayload := "testtest"
|
||||
attach, err := attachment.NewAttachment(&repo_model.Attachment{
|
||||
RepoID: repo.ID,
|
||||
UploaderID: user.ID,
|
||||
Name: "test.txt",
|
||||
}, strings.NewReader(samplePayload), int64(len([]byte(samplePayload))))
|
||||
}, strings.NewReader("testtest"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, UpdateRelease(user, gitRepo, release, []string{attach.UUID}, nil, nil))
|
||||
|
@ -51,7 +51,7 @@
|
||||
{{JsPrettyNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
</span>
|
||||
</div>
|
||||
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
|
||||
{{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}}
|
||||
<div class="ui right operate">
|
||||
<a href="{{$.Link}}/{{.ID}}/edit" data-id={{.ID}} data-title={{.Title}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
|
||||
{{if .IsClosed}}
|
||||
@ -59,7 +59,7 @@
|
||||
{{else}}
|
||||
<a class="link-action" href data-url="{{$.Link}}/{{.ID}}/close">{{svg "octicon-skip"}} {{$.locale.Tr "repo.projects.close"}}</a>
|
||||
{{end}}
|
||||
<a class="delete-button" href="#" data-url="{{$.Link}}/{{.ID}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
||||
<a class="delete-button" href="#" data-url="{{$.RepoLink}}/projects/{{.ID}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Description}}
|
||||
@ -75,7 +75,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if $.CanWriteProjects}}
|
||||
{{if or .CanWriteIssues .CanWritePulls}}
|
||||
<div class="ui small basic delete modal">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-trash"}}
|
||||
|
@ -43,7 +43,7 @@
|
||||
<h2 class="project-title">{{$.Project.Title}}</h2>
|
||||
<div class="content project-description">{{$.Project.RenderedContent|Str2html}}</div>
|
||||
</div>
|
||||
{{if $.CanWriteProjects}}
|
||||
{{if or $.CanWriteIssues $.CanWritePulls}}
|
||||
<div class="column right aligned">
|
||||
<div class="ui compact right small menu">
|
||||
<a class="item" href="{{$.Link}}/edit?redirect=project" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
|
||||
@ -128,7 +128,7 @@
|
||||
|
||||
<div class="text right actions">
|
||||
<div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
|
||||
<button data-url="{{$.Link}}/{{.ID}}" class="ui primary button edit-column-button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
|
||||
<button data-url="{{$.Link}}/{{.ID}}" class="ui primary button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -256,7 +256,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
{{if .CanWriteProjects}}
|
||||
{{if or .CanWriteIssues .CanWritePulls}}
|
||||
<div class="ui small basic delete modal">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-trash"}}
|
||||
|
@ -1,43 +0,0 @@
|
||||
<div class="ui {{if or (not .HasIssuesOrPullsWritePermission) .Repository.IsArchived}}disabled{{end}} floating jump select-label dropdown">
|
||||
<a class="text gt-df gt-ac muted">
|
||||
<strong>{{.locale.Tr "repo.issues.new.labels"}}</strong>
|
||||
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
||||
{{svg "octicon-gear" 16 "gt-ml-2"}}
|
||||
{{end}}
|
||||
</a>
|
||||
<div class="filter menu" {{if .Issue}}data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/labels"{{else}}data-id="#label_ids"{{end}}>
|
||||
<div class="header" style="text-transform: none;font-size:16px;">{{.locale.Tr "repo.issues.new.add_labels_title"}}</div>
|
||||
{{if or .Labels .OrgLabels}}
|
||||
<div class="ui icon search input">
|
||||
<i class="icon gt-df gt-ac gt-jc">{{svg "octicon-search" 16}}</i>
|
||||
<input type="text" placeholder="{{.locale.Tr "repo.issues.filter_labels"}}">
|
||||
</div>
|
||||
{{end}}
|
||||
<a class="no-select item" href="#">{{.locale.Tr "repo.issues.new.clear_labels"}}</a>
|
||||
{{if or .Labels .OrgLabels}}
|
||||
{{$previousExclusiveScope := "_no_scope"}}
|
||||
{{range .Labels}}
|
||||
{{$exclusiveScope := .ExclusiveScope}}
|
||||
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
|
||||
<div class="ui divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
<div class="ui divider"></div>
|
||||
{{$previousExclusiveScope := "_no_scope"}}
|
||||
{{range .OrgLabels}}
|
||||
{{$exclusiveScope := .ExclusiveScope}}
|
||||
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
|
||||
<div class="ui divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<div class="header" style="text-transform: none;font-size:14px;">{{.locale.Tr "repo.issues.new.no_items"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
@ -36,7 +36,50 @@
|
||||
{{template "repo/issue/branch_selector_field" .}}
|
||||
|
||||
<input id="label_ids" name="label_ids" type="hidden" value="{{.label_ids}}">
|
||||
{{template "repo/issue/labels/labels_selector_field" .}}
|
||||
<div class="ui {{if not .HasIssuesOrPullsWritePermission}}disabled{{end}} floating jump select-label dropdown">
|
||||
<span class="text">
|
||||
<strong>{{.locale.Tr "repo.issues.new.labels"}}</strong>
|
||||
{{if .HasIssuesOrPullsWritePermission}}
|
||||
{{svg "octicon-gear"}}
|
||||
{{end}}
|
||||
</span>
|
||||
<div class="filter menu" data-id="#label_ids">
|
||||
<div class="header" style="text-transform: none;font-size:16px;">{{.locale.Tr "repo.issues.new.add_labels_title"}}</div>
|
||||
{{if or .Labels .OrgLabels}}
|
||||
<div class="ui icon search input">
|
||||
<i class="icon gt-df gt-ac gt-jc">{{svg "octicon-search" 16}}</i>
|
||||
<input type="text" placeholder="{{.locale.Tr "repo.issues.filter_labels"}}">
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="no-select item">{{.locale.Tr "repo.issues.new.clear_labels"}}</div>
|
||||
{{if or .Labels .OrgLabels}}
|
||||
{{$previousExclusiveScope := "_no_scope"}}
|
||||
{{range .Labels}}
|
||||
{{$exclusiveScope := .ExclusiveScope}}
|
||||
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
|
||||
<div class="ui divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
|
||||
<div class="ui divider"></div>
|
||||
{{$previousExclusiveScope := "_no_scope"}}
|
||||
{{range .OrgLabels}}
|
||||
{{$exclusiveScope := .ExclusiveScope}}
|
||||
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
|
||||
<div class="ui divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<div class="header" style="text-transform: none;font-size:14px;">{{.locale.Tr "repo.issues.new.no_items"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "repo/issue/labels/labels_sidebar" dict "root" $}}
|
||||
|
||||
<div class="ui divider"></div>
|
||||
|
@ -106,7 +106,49 @@
|
||||
<div class="ui divider"></div>
|
||||
{{end}}
|
||||
|
||||
{{template "repo/issue/labels/labels_selector_field" .}}
|
||||
<div class="ui {{if or (not .HasIssuesOrPullsWritePermission) .Repository.IsArchived}}disabled{{end}} floating jump select-label dropdown">
|
||||
<a class="text gt-df gt-ac muted">
|
||||
<strong>{{.locale.Tr "repo.issues.new.labels"}}</strong>
|
||||
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
||||
{{svg "octicon-gear" 16 "gt-ml-2"}}
|
||||
{{end}}
|
||||
</a>
|
||||
<div class="filter menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/labels">
|
||||
<div class="header" style="text-transform: none;font-size:16px;">{{.locale.Tr "repo.issues.new.add_labels_title"}}</div>
|
||||
{{if or .Labels .OrgLabels}}
|
||||
<div class="ui icon search input">
|
||||
<i class="icon gt-df gt-ac gt-jc">{{svg "octicon-search" 16}}</i>
|
||||
<input type="text" placeholder="{{.locale.Tr "repo.issues.filter_labels"}}">
|
||||
</div>
|
||||
{{end}}
|
||||
<a class="no-select item" href="#">{{.locale.Tr "repo.issues.new.clear_labels"}}</a>
|
||||
{{if or .Labels .OrgLabels}}
|
||||
{{$previousExclusiveScope := "_no_scope"}}
|
||||
{{range .Labels}}
|
||||
{{$exclusiveScope := .ExclusiveScope}}
|
||||
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
|
||||
<div class="ui divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
<div class="ui divider"></div>
|
||||
{{$previousExclusiveScope := "_no_scope"}}
|
||||
{{range .OrgLabels}}
|
||||
{{$exclusiveScope := .ExclusiveScope}}
|
||||
{{if and (ne $previousExclusiveScope "_no_scope") (ne $previousExclusiveScope $exclusiveScope)}}
|
||||
<div class="ui divider"></div>
|
||||
{{end}}
|
||||
{{$previousExclusiveScope = $exclusiveScope}}
|
||||
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span> {{RenderLabel $.Context .}}
|
||||
{{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<div class="header" style="text-transform: none;font-size:14px;">{{.locale.Tr "repo.issues.new.no_items"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "repo/issue/labels/labels_sidebar" dict "root" $}}
|
||||
|
||||
<div class="ui divider"></div>
|
||||
|
@ -53,15 +53,15 @@
|
||||
{{JsPrettyNumber .NumClosedIssues}} {{$.locale.Tr "repo.issues.closed_title"}}
|
||||
</span>
|
||||
</div>
|
||||
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
|
||||
{{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}}
|
||||
<div class="ui right operate">
|
||||
<a href="{{.Link}}/edit" data-id={{.ID}} data-title={{.Title}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
|
||||
<a href="{{$.Link}}/{{.ID}}/edit" data-id={{.ID}} data-title={{.Title}}>{{svg "octicon-pencil"}} {{$.locale.Tr "repo.issues.label_edit"}}</a>
|
||||
{{if .IsClosed}}
|
||||
<a class="link-action" href data-url="{{.Link}}/open">{{svg "octicon-check"}} {{$.locale.Tr "repo.projects.open"}}</a>
|
||||
<a class="link-action" href data-url="{{$.Link}}/{{.ID}}/open">{{svg "octicon-check"}} {{$.locale.Tr "repo.projects.open"}}</a>
|
||||
{{else}}
|
||||
<a class="link-action" href data-url="{{.Link}}/close">{{svg "octicon-skip"}} {{$.locale.Tr "repo.projects.close"}}</a>
|
||||
<a class="link-action" href data-url="{{$.Link}}/{{.ID}}/close">{{svg "octicon-skip"}} {{$.locale.Tr "repo.projects.close"}}</a>
|
||||
{{end}}
|
||||
<a class="delete-button" href="#" data-url="{{.Link}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
||||
<a class="delete-button" href="#" data-url="{{$.RepoLink}}/projects/{{.ID}}/delete" data-id="{{.ID}}">{{svg "octicon-trash"}} {{$.locale.Tr "repo.issues.label_delete"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Description}}
|
||||
@ -77,7 +77,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .CanWriteProjects}}
|
||||
{{if or .CanWriteIssues .CanWritePulls}}
|
||||
<div class="ui small basic delete modal">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-trash"}}
|
||||
|
@ -95,35 +95,39 @@ export function initRepoProject() {
|
||||
$('.edit-project-board').each(function () {
|
||||
const projectHeader = $(this).closest('.board-column-header');
|
||||
const projectTitleLabel = projectHeader.find('.board-label');
|
||||
const projectTitleInput = $(this).find('.project-board-title');
|
||||
const projectColorInput = $(this).find('#new_board_color');
|
||||
const projectTitleInput = $(this).find(
|
||||
'.content > .form > .field > .project-board-title',
|
||||
);
|
||||
const projectColorInput = $(this).find('.content > .form > .field #new_board_color');
|
||||
const boardColumn = $(this).closest('.board-column');
|
||||
|
||||
if (boardColumn.css('backgroundColor')) {
|
||||
setLabelColor(projectHeader, rgbToHex(boardColumn.css('backgroundColor')));
|
||||
}
|
||||
|
||||
$(this).find('.edit-column-button').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$(this)
|
||||
.find('.content > .form > .actions > .red')
|
||||
.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
url: $(this).data('url'),
|
||||
data: JSON.stringify({title: projectTitleInput.val(), color: projectColorInput.val()}),
|
||||
headers: {
|
||||
'X-Csrf-Token': csrfToken,
|
||||
},
|
||||
contentType: 'application/json',
|
||||
method: 'PUT',
|
||||
}).done(() => {
|
||||
projectTitleLabel.text(projectTitleInput.val());
|
||||
projectTitleInput.closest('form').removeClass('dirty');
|
||||
if (projectColorInput.val()) {
|
||||
setLabelColor(projectHeader, projectColorInput.val());
|
||||
}
|
||||
boardColumn.attr('style', `background: ${projectColorInput.val()}!important`);
|
||||
$('.ui.modal').modal('hide');
|
||||
$.ajax({
|
||||
url: $(this).data('url'),
|
||||
data: JSON.stringify({title: projectTitleInput.val(), color: projectColorInput.val()}),
|
||||
headers: {
|
||||
'X-Csrf-Token': csrfToken,
|
||||
},
|
||||
contentType: 'application/json',
|
||||
method: 'PUT',
|
||||
}).done(() => {
|
||||
projectTitleLabel.text(projectTitleInput.val());
|
||||
projectTitleInput.closest('form').removeClass('dirty');
|
||||
if (projectColorInput.val()) {
|
||||
setLabelColor(projectHeader, projectColorInput.val());
|
||||
}
|
||||
boardColumn.attr('style', `background: ${projectColorInput.val()}!important`);
|
||||
$('.ui.modal').modal('hide');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.set-default-project-board', async function (e) {
|
||||
|
@ -2838,11 +2838,11 @@
|
||||
|
||||
.labels-list .label {
|
||||
margin: 2px 0;
|
||||
display: inline-flex !important;
|
||||
display: inline-block !important;
|
||||
line-height: 1.3em; // there is a `font-size: 1.25em` for inside emoji, so here the line-height needs to be larger slightly
|
||||
}
|
||||
|
||||
// Scoped labels with different colors on left and right
|
||||
// Scoped labels with different colors on left and right, and slanted divider in the middle
|
||||
.scope-parent {
|
||||
background: none !important;
|
||||
padding: 0 !important;
|
||||
@ -2851,12 +2851,23 @@
|
||||
.ui.label.scope-left {
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
padding-right: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.ui.label.scope-middle {
|
||||
width: 12px;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.ui.label.scope-right {
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user