mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-27 09:54:15 -05:00
bbffcc3aec
There are multiple places where Gitea does not properly escape URLs that it is building and there are multiple places where it builds urls when there is already a simpler function available to use this. This is an extensive PR attempting to fix these issues. 1. The first commit in this PR looks through all href, src and links in the Gitea codebase and has attempted to catch all the places where there is potentially incomplete escaping. 2. Whilst doing this we will prefer to use functions that create URLs over recreating them by hand. 3. All uses of strings should be directly escaped - even if they are not currently expected to contain escaping characters. The main benefit to doing this will be that we can consider relaxing the constraints on user names and reponames in future. 4. The next commit looks at escaping in the wiki and re-considers the urls that are used there. Using the improved escaping here wiki files containing '/'. (This implementation will currently still place all of the wiki files the root directory of the repo but this would not be difficult to change.) 5. The title generation in feeds is now properly escaped. 6. EscapePound is no longer needed - urls should be PathEscaped / QueryEscaped as necessary but then re-escaped with Escape when creating html with locales Signed-off-by: Andrew Thornton <art27@cantab.net> Signed-off-by: Andrew Thornton <art27@cantab.net>
650 lines
27 KiB
Handlebars
650 lines
27 KiB
Handlebars
<div class="four wide column">
|
|
<div class="ui segment metas">
|
|
{{template "repo/issue/branch_selector_field" .}}
|
|
|
|
{{if .Issue.IsPull }}
|
|
|
|
<input id="reviewer_id" name="reviewer_id" type="hidden" value="{{.reviewer_id}}">
|
|
<div class="ui {{if or (not .Reviewers) (not .CanChooseReviewer) .Repository.IsArchived}}disabled{{end}} floating jump select-reviewers-modify dropdown">
|
|
<a class="text df ac muted">
|
|
<strong>{{.i18n.Tr "repo.issues.review.reviewers"}}</strong>
|
|
{{if and .CanChooseReviewer (not .Repository.IsArchived)}}
|
|
{{svg "octicon-gear" 16 "ml-2"}}
|
|
{{end}}
|
|
</a>
|
|
<div class="filter menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/request_review">
|
|
<div class="header" style="text-transform: none;font-size:16px;">{{.i18n.Tr "repo.issues.new.add_reviewer_title"}}</div>
|
|
{{if .Reviewers}}
|
|
<div class="ui icon search input">
|
|
<i class="icon df ac jc">{{svg "octicon-search" 16}}</i>
|
|
<input type="text" placeholder="{{.i18n.Tr "repo.issues.filter_reviewers"}}">
|
|
</div>
|
|
{{end}}
|
|
{{if .Reviewers}}
|
|
{{range .Reviewers}}
|
|
{{if .User}}
|
|
<a class="{{if not .CanChange}}ui poping up{{end}} item {{if .Checked}} checked {{end}} {{if not .CanChange}}ban-change{{end}}" href="#" data-id="{{.ItemID}}" data-id-selector="#review_request_{{.ItemID}}" {{if not .CanChange}} data-content="{{$.i18n.Tr "repo.issues.remove_request_review_block"}}"{{end}}>
|
|
<span class="octicon-check {{if not .Checked}}invisible{{end}}">{{svg "octicon-check"}}</span>
|
|
<span class="text">
|
|
{{avatar .User 28 "mr-3"}}
|
|
{{.User.GetDisplayName}}
|
|
</span>
|
|
</a>
|
|
{{end}}
|
|
{{end}}
|
|
{{end}}
|
|
{{if .TeamReviewers}}
|
|
<div class="ui divider"></div>
|
|
{{range .TeamReviewers}}
|
|
{{if .Team}}
|
|
<a class="{{if not .CanChange}}ui poping up{{end}} item {{if .Checked}} checked {{end}} {{if not .CanChange}}ban-change{{end}}" href="#" data-id="{{.ItemID}}" data-id-selector="#review_request_team_{{.Team.ID}}" {{if not .CanChange}} data-content="{{$.i18n.Tr "repo.issues.remove_request_review_block"}}"{{end}}>
|
|
<span class="octicon-check {{if not .Checked}}invisible{{end}}">{{svg "octicon-check" 16}}</span>
|
|
<span class="text">
|
|
{{svg "octicon-people" 16 "ml-4 mr-2"}}{{$.Issue.Repo.OwnerName}}/{{.Team.Name}}
|
|
</span>
|
|
</a>
|
|
{{end}}
|
|
{{end}}
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui assignees list">
|
|
<span class="no-select item {{if or .OriginalReviews .PullReviewers}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_reviewers"}}</span>
|
|
<div class="selected">
|
|
{{range .PullReviewers}}
|
|
<div class="item mb-2">
|
|
{{if .User}}
|
|
<a class="muted sidebar-item-link" href="{{.User.HomeLink}}">
|
|
{{avatar .User 28 "mr-3"}}
|
|
{{.User.GetDisplayName}}
|
|
</a>
|
|
{{else if .Team}}
|
|
<span class="text">{{svg "octicon-people" 16 "teamavatar"}}{{$.Issue.Repo.OwnerName}}/{{.Team.Name}}</span>
|
|
{{end}}
|
|
<span class="ui right type-icon text {{if eq .Review.Type 1}}green
|
|
{{- else if eq .Review.Type 2}}grey
|
|
{{- else if eq .Review.Type 3}}red
|
|
{{- else if eq .Review.Type 4}}yellow
|
|
{{- else}}grey{{end}} right ">
|
|
|
|
{{if .CanChange}}
|
|
<a href="#" class="ui poping up icon re-request-review {{if .Checked}}checked{{end}}" data-content="{{if .Checked}} {{$.i18n.Tr "repo.issues.remove_request_review"}} {{else}} {{$.i18n.Tr "repo.issues.re_request_review"}} {{end}}" data-issue-id="{{$.Issue.ID}}" data-id="{{.ItemID}}" data-update-url="{{$.RepoLink}}/issues/request_review">
|
|
{{if .Checked}} {{svg "octicon-trash"}} {{else}} {{svg "octicon-sync"}} {{end}}
|
|
</a>
|
|
{{end}}
|
|
{{svg (printf "octicon-%s" .Review.Type.Icon)}}
|
|
</span>
|
|
</div>
|
|
{{end}}
|
|
{{range .OriginalReviews}}
|
|
<div class="item" style="margin-bottom: 10px;">
|
|
<a href="{{$.Repository.OriginalURL}}" class="ui poping up" data-content="{{$.i18n.Tr "repo.migrated_from_fake" ($.Repository.GetOriginalURLHostname|Escape) | Safe }}">
|
|
<span class="text black">
|
|
{{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
|
|
{{ .OriginalAuthor }}
|
|
</span>
|
|
</a>
|
|
<span class="ui right type-icon text {{if eq .Type 1}}green
|
|
{{- else if eq .Type 2}}grey
|
|
{{- else if eq .Type 3}}red
|
|
{{- else if eq .Type 4}}yellow
|
|
{{- else}}grey{{end}} right ">
|
|
{{svg (printf "octicon-%s" .Type.Icon)}}
|
|
</span>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .HasMerged) (not .Issue.IsClosed) (not .IsPullWorkInProgress)}}
|
|
<div class="toggle-wip" data-title="{{.Issue.Title}}" data-wip-prefix="{{(index .PullRequestWorkInProgressPrefixes 0| Escape)}}" data-update-url="{{.Issue.Link}}/title">
|
|
<a class="muted">
|
|
{{.i18n.Tr "repo.pulls.still_in_progress"}} {{.i18n.Tr "repo.pulls.add_prefix" (index .PullRequestWorkInProgressPrefixes 0| Escape) | Safe}}
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
<div class="ui divider"></div>
|
|
{{end}}
|
|
|
|
<div class="ui {{if or (not .HasIssuesOrPullsWritePermission) .Repository.IsArchived}}disabled{{end}} floating jump select-label dropdown">
|
|
<a class="text df ac muted">
|
|
<strong>{{.i18n.Tr "repo.issues.new.labels"}}</strong>
|
|
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
|
{{svg "octicon-gear" 16 "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;">{{.i18n.Tr "repo.issues.new.add_labels_title"}}</div>
|
|
{{if or .Labels .OrgLabels}}
|
|
<div class="ui icon search input">
|
|
<i class="icon df ac jc">{{svg "octicon-search" 16}}</i>
|
|
<input type="text" placeholder="{{.i18n.Tr "repo.issues.filter_labels"}}">
|
|
</div>
|
|
{{end}}
|
|
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_labels"}}</div>
|
|
{{if or .Labels .OrgLabels}}
|
|
{{range .Labels}}
|
|
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{svg "octicon-check"}}</span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name | RenderEmoji}}
|
|
{{if .Description }}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}</a>
|
|
{{end}}
|
|
<div class="ui divider"></div>
|
|
{{range .OrgLabels}}
|
|
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{svg "octicon-check"}}</span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name | RenderEmoji}}
|
|
{{if .Description }}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}</a>
|
|
{{end}}
|
|
{{else}}
|
|
<div class="header" style="text-transform: none;font-size:14px;">{{.i18n.Tr "repo.issues.new.no_items"}}</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{template "repo/issue/labels/labels_sidebar" dict "root" $ "ctx" .}}
|
|
|
|
<div class="ui divider"></div>
|
|
|
|
<div class="ui {{if or (not .HasIssuesOrPullsWritePermission) .Repository.IsArchived}}disabled{{end}} floating jump select-milestone dropdown">
|
|
<a class="text df ac muted">
|
|
<strong>{{.i18n.Tr "repo.issues.new.milestone"}}</strong>
|
|
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
|
{{svg "octicon-gear" 16 "ml-2"}}
|
|
{{end}}
|
|
</a>
|
|
<div class="menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/milestone">
|
|
<div class="header" style="text-transform: none;font-size:16px;">{{.i18n.Tr "repo.issues.new.add_milestone_title"}}</div>
|
|
{{if or .OpenMilestones .ClosedMilestones}}
|
|
<div class="ui icon search input">
|
|
<i class="icon df ac jc">{{svg "octicon-search" 16}}</i>
|
|
<input type="text" placeholder="{{.i18n.Tr "repo.issues.filter_milestones"}}">
|
|
</div>
|
|
{{end}}
|
|
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_milestone"}}</div>
|
|
{{if and (not .OpenMilestones) (not .ClosedMilestones)}}
|
|
<div class="header" style="text-transform: none;font-size:14px;">
|
|
{{.i18n.Tr "repo.issues.new.no_items"}}
|
|
</div>
|
|
{{else}}
|
|
{{if .OpenMilestones}}
|
|
<div class="divider"></div>
|
|
<div class="header">
|
|
{{.i18n.Tr "repo.issues.new.open_milestone"}}
|
|
</div>
|
|
{{range .OpenMilestones}}
|
|
<a class="item" data-id="{{.ID}}" data-href="{{$.RepoLink}}/issues?milestone={{.ID}}">
|
|
{{svg "octicon-milestone" 16 "mr-2"}}
|
|
{{.Name}}
|
|
</a>
|
|
{{end}}
|
|
{{end}}
|
|
{{if .ClosedMilestones}}
|
|
<div class="divider"></div>
|
|
<div class="header">
|
|
{{.i18n.Tr "repo.issues.new.closed_milestone"}}
|
|
</div>
|
|
{{range .ClosedMilestones}}
|
|
<a class="item" data-id="{{.ID}}" data-href="{{$.RepoLink}}/issues?milestone={{.ID}}">
|
|
{{svg "octicon-milestone" 16 "mr-2"}}
|
|
{{.Name}}
|
|
</a>
|
|
{{end}}
|
|
{{end}}
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
<div class="ui select-milestone list">
|
|
<span class="no-select item {{if .Issue.Milestone}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_milestone"}}</span>
|
|
<div class="selected">
|
|
{{if .Issue.Milestone}}
|
|
<a class="item muted sidebar-item-link" href="{{.RepoLink}}/milestone/{{.Issue.Milestone.ID}}">
|
|
{{svg "octicon-milestone" 18 "mr-3"}}
|
|
{{.Issue.Milestone.Name}}
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
{{if .IsProjectsEnabled}}
|
|
<div class="ui divider"></div>
|
|
|
|
<div class="ui {{if or (not .HasIssuesOrPullsWritePermission) .Repository.IsArchived}}disabled{{end}} floating jump select-project dropdown">
|
|
<a class="text df ac muted">
|
|
<strong>{{.i18n.Tr "repo.issues.new.projects"}}</strong>
|
|
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
|
{{svg "octicon-gear" 16 "ml-2"}}
|
|
{{end}}
|
|
</a>
|
|
<div class="menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/projects">
|
|
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_projects"}}</div>
|
|
{{if .OpenProjects}}
|
|
<div class="divider"></div>
|
|
<div class="header">
|
|
{{.i18n.Tr "repo.issues.new.open_projects"}}
|
|
</div>
|
|
{{range .OpenProjects}}
|
|
<a class="item muted sidebar-item-link" data-id="{{.ID}}" data-href="{{$.RepoLink}}/projects/{{.ID}}">
|
|
{{svg "octicon-project" 18 "mr-3"}}
|
|
{{.Title}}
|
|
</a>
|
|
{{end}}
|
|
{{end}}
|
|
{{if .ClosedProjects}}
|
|
<div class="divider"></div>
|
|
<div class="header">
|
|
{{.i18n.Tr "repo.issues.new.closed_projects"}}
|
|
</div>
|
|
{{range .ClosedProjects}}
|
|
<a class="item muted sidebar-item-link" data-id="{{.ID}}" data-href="{{$.RepoLink}}/projects/{{.ID}}">
|
|
{{svg "octicon-project" 18 "mr-3"}}
|
|
{{.Title}}
|
|
</a>
|
|
{{end}}
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
<div class="ui select-project list">
|
|
<span class="no-select item {{if .Issue.ProjectID}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_projects"}}</span>
|
|
<div class="selected">
|
|
{{if .Issue.ProjectID}}
|
|
<a class="item muted sidebar-item-link" href="{{.RepoLink}}/projects/{{.Issue.ProjectID}}">
|
|
{{svg "octicon-project" 18 "mr-3"}}
|
|
{{.Issue.Project.Title}}
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="ui divider"></div>
|
|
|
|
<input id="assignee_id" name="assignee_id" type="hidden" value="{{.assignee_id}}">
|
|
<div class="ui {{if or (not .HasIssuesOrPullsWritePermission) .Repository.IsArchived}}disabled{{end}} floating jump select-assignees-modify dropdown">
|
|
<a class="text df ac muted">
|
|
<strong>{{.i18n.Tr "repo.issues.new.assignees"}}</strong>
|
|
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
|
{{svg "octicon-gear" 16 "ml-2"}}
|
|
{{end}}
|
|
</a>
|
|
<div class="filter menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/assignee">
|
|
<div class="header" style="text-transform: none;font-size:16px;">{{.i18n.Tr "repo.issues.new.add_assignees_title"}}</div>
|
|
<div class="ui icon search input">
|
|
<i class="icon df ac jc">{{svg "octicon-search" 16}}</i>
|
|
<input type="text" placeholder="{{.i18n.Tr "repo.issues.filter_assignees"}}">
|
|
</div>
|
|
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_assignees"}}</div>
|
|
{{range .Assignees}}
|
|
|
|
{{$AssigneeID := .ID}}
|
|
<a class="item{{range $.Issue.Assignees}}{{if eq .ID $AssigneeID}} checked{{end}}{{end}}" href="#" data-id="{{.ID}}" data-id-selector="#assignee_{{.ID}}">
|
|
{{$checked := false}}
|
|
{{range $.Issue.Assignees}}
|
|
{{if eq .ID $AssigneeID}}
|
|
{{$checked = true}}
|
|
{{end}}
|
|
{{end}}
|
|
<span class="octicon-check {{if not $checked}}invisible{{end}}">{{svg "octicon-check"}}</span>
|
|
<span class="text">
|
|
{{avatar . 28 "mr-3"}}
|
|
{{.GetDisplayName}}
|
|
</span>
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
<div class="ui assignees list">
|
|
<span class="no-select item {{if .Issue.Assignees}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_assignees"}}</span>
|
|
<div class="selected">
|
|
{{range .Issue.Assignees}}
|
|
<div class="item">
|
|
<a class="muted sidebar-item-link" href="{{$.RepoLink}}/{{if $.Issue.IsPull}}pulls{{else}}issues{{end}}?assignee={{.ID}}">
|
|
{{avatar . 28 "mr-3"}}
|
|
{{.GetDisplayName}}
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui divider"></div>
|
|
|
|
{{if .Participants}}
|
|
<span class="text"><strong>{{.i18n.Tr "repo.issues.num_participants" .NumParticipants}}</strong></span>
|
|
<div class="ui list df fw">
|
|
{{range .Participants}}
|
|
<a class="ui poping up" {{if gt .ID 0}}href="{{.HomeLink}}"{{end}} data-content="{{.GetDisplayName}}" data-position="top center" data-variation="small inverted">
|
|
{{avatar . 28 "my-1 mr-2"}}
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if and $.IssueWatch (not .Repository.IsArchived)}}
|
|
<div class="ui divider"></div>
|
|
|
|
<div class="ui watching">
|
|
<span class="text"><strong>{{.i18n.Tr "notification.notifications"}}</strong></span>
|
|
<div class="mt-3">
|
|
<form method="POST" action="{{.Issue.Link}}/watch">
|
|
<input type="hidden" name="watch" value="{{if $.IssueWatch.IsWatching}}0{{else}}1{{end}}" />
|
|
{{$.CsrfTokenHtml}}
|
|
<button class="fluid ui button df jc">
|
|
{{if $.IssueWatch.IsWatching}}
|
|
{{svg "octicon-mute" 16 "mr-3"}}
|
|
{{.i18n.Tr "repo.issues.unsubscribe"}}
|
|
{{else}}
|
|
{{svg "octicon-unmute" 16 "mr-3"}}
|
|
{{.i18n.Tr "repo.issues.subscribe"}}
|
|
{{end}}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
{{if .Repository.IsTimetrackerEnabled }}
|
|
{{if and .CanUseTimetracker (not .Repository.IsArchived)}}
|
|
<div class="ui divider"></div>
|
|
<div class="ui timetrack">
|
|
<span class="text"><strong>{{.i18n.Tr "repo.issues.tracker"}}</strong></span>
|
|
<div class="mt-3">
|
|
<form method="POST" action="{{.Issue.Link}}/times/stopwatch/toggle" id="toggle_stopwatch_form">
|
|
{{$.CsrfTokenHtml}}
|
|
</form>
|
|
<form method="POST" action="{{.Issue.Link}}/times/stopwatch/cancel" id="cancel_stopwatch_form">
|
|
{{$.CsrfTokenHtml}}
|
|
</form>
|
|
{{if $.IsStopwatchRunning}}
|
|
<button class="ui fluid button issue-stop-time">{{.i18n.Tr "repo.issues.stop_tracking"}}</button>
|
|
<button class="ui fluid negative button issue-cancel-time mt-3">{{.i18n.Tr "repo.issues.cancel_tracking"}}</button>
|
|
{{else}}
|
|
{{if .HasUserStopwatch}}
|
|
<div class="ui warning message">
|
|
{{.i18n.Tr "repo.issues.tracking_already_started" (.OtherStopwatchURL|Escape) | Safe}}
|
|
</div>
|
|
{{end}}
|
|
<button class="ui fluid button poping up issue-start-time" data-content='{{.i18n.Tr "repo.issues.start_tracking"}}' data-position="top center" data-variation="small inverted">{{.i18n.Tr "repo.issues.start_tracking_short"}}</button>
|
|
<div class="ui mini modal issue-start-time-modal">
|
|
<div class="header">{{.i18n.Tr "repo.issues.add_time"}}</div>
|
|
<div class="content">
|
|
<form method="POST" id="add_time_manual_form" action="{{.Issue.Link}}/times/add" class="ui action input fluid">
|
|
{{$.CsrfTokenHtml}}
|
|
<input placeholder='{{.i18n.Tr "repo.issues.add_time_hours"}}' type="number" name="hours">
|
|
<input placeholder='{{.i18n.Tr "repo.issues.add_time_minutes"}}' type="number" name="minutes" class="ui compact">
|
|
</form>
|
|
</div>
|
|
<div class="actions">
|
|
<div class="ui green approve button">{{.i18n.Tr "repo.issues.add_time_short"}}</div>
|
|
<div class="ui red cancel button">{{.i18n.Tr "repo.issues.add_time_cancel"}}</div>
|
|
</div>
|
|
</div>
|
|
<button class="ui fluid button green poping up issue-add-time mt-3" data-content='{{.i18n.Tr "repo.issues.add_time"}}' data-position="top center" data-variation="small inverted">{{.i18n.Tr "repo.issues.add_time_short"}}</button>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
{{if gt (len .WorkingUsers) 0}}
|
|
<div class="ui divider"></div>
|
|
<div class="ui comments">
|
|
<span class="text"><strong>{{.i18n.Tr "repo.issues.time_spent_from_all_authors" ($.Issue.TotalTrackedTime | Sec2Time) | Safe}}</strong></span>
|
|
<div>
|
|
{{range $user, $trackedtime := .WorkingUsers}}
|
|
<div class="comment mt-3">
|
|
<a class="avatar">
|
|
{{avatar $user}}
|
|
</a>
|
|
<div class="content">
|
|
<a class="author">{{$user.DisplayName}}</a>
|
|
<div class="text">
|
|
{{$trackedtime}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
|
|
<div class="ui divider"></div>
|
|
<span class="text"><strong>{{.i18n.Tr "repo.issues.due_date"}}</strong></span>
|
|
<div class="ui form" id="deadline-loader">
|
|
<div class="ui negative message" id="deadline-err-invalid-date" style="display: none;">
|
|
{{svg "octicon-x" 16 "close icon"}}
|
|
{{.i18n.Tr "repo.issues.due_date_invalid"}}
|
|
</div>
|
|
{{if ne .Issue.DeadlineUnix 0}}
|
|
<p>
|
|
<div class="df sb ac">
|
|
<div class="due-date poping up {{if .Issue.IsOverdue}}text red{{end}}" {{if .Issue.IsOverdue}}data-content="{{.i18n.Tr "repo.issues.due_date_overdue"}}"{{end}}>
|
|
{{svg "octicon-calendar" 16 "mr-3"}}
|
|
{{.Issue.DeadlineUnix.FormatDate}}
|
|
</div>
|
|
<div>
|
|
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
|
<a class="issue-due-edit poping up muted" data-content="{{$.i18n.Tr "repo.issues.due_date_form_edit"}}">{{svg "octicon-pencil" 16 "mr-2"}}</a>
|
|
<a class="issue-due-remove poping up muted" data-content="{{$.i18n.Tr "repo.issues.due_date_form_remove"}}">{{svg "octicon-trash"}}</a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</p>
|
|
{{else}}
|
|
<p><i>{{.i18n.Tr "repo.issues.due_date_not_set"}}</i></p>
|
|
{{end}}
|
|
|
|
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
|
|
<div {{if ne .Issue.DeadlineUnix 0}} style="display: none;"{{end}} id="deadlineForm">
|
|
<form class="ui fluid action input issue-due-form" action="{{AppSubUrl}}/api/v1/repos/{{PathEscape .Repository.Owner.Name}}/{{PathEscape .Repository.Name}}/issues/{{.Issue.Index}}" method="post" id="update-issue-deadline-form">
|
|
{{$.CsrfTokenHtml}}
|
|
<input required placeholder="{{.i18n.Tr "repo.issues.due_date_form"}}" {{if gt .Issue.DeadlineUnix 0}}value="{{.Issue.DeadlineUnix.Format "2006-01-02"}}"{{end}} type="date" name="deadlineDate" id="deadlineDate">
|
|
<button class="ui green icon button">
|
|
{{if ne .Issue.DeadlineUnix 0}}
|
|
{{svg "octicon-pencil"}}
|
|
{{else}}
|
|
{{svg "octicon-plus"}}
|
|
{{end}}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
{{if .Repository.IsDependenciesEnabled}}
|
|
<div class="ui divider"></div>
|
|
|
|
<div class="ui depending">
|
|
{{if (and (not .BlockedByDependencies) (not .BlockingDependencies))}}
|
|
<span class="text"><strong>{{.i18n.Tr "repo.issues.dependency.title"}}</strong></span>
|
|
<br>
|
|
<p>
|
|
{{if .Issue.IsPull}}
|
|
{{.i18n.Tr "repo.issues.dependency.pr_no_dependencies"}}
|
|
{{else}}
|
|
{{.i18n.Tr "repo.issues.dependency.issue_no_dependencies"}}
|
|
{{end}}
|
|
</p>
|
|
{{end}}
|
|
|
|
{{if .BlockingDependencies}}
|
|
<span class="text poping up" data-content="{{if .Issue.IsPull}}{{.i18n.Tr "repo.issues.dependency.pr_close_blocks"}}{{else}}{{.i18n.Tr "repo.issues.dependency.issue_close_blocks"}}{{end}}">
|
|
<strong>{{.i18n.Tr "repo.issues.dependency.blocks_short"}}</strong>
|
|
</span>
|
|
<div class="ui relaxed divided list">
|
|
{{range .BlockingDependencies}}
|
|
<div class="item dependency{{if .Issue.IsClosed}} is-closed{{end}} df ac sb">
|
|
<div class="item-left df jc fc f1">
|
|
<a class="title" href="{{.Issue.Link}}">
|
|
#{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}
|
|
</a>
|
|
<div class="text small">
|
|
{{.Repository.OwnerName}}/{{.Repository.Name}}
|
|
</div>
|
|
</div>
|
|
<div class="item-right df ac">
|
|
{{if and $.CanCreateIssueDependencies (not $.Repository.IsArchived)}}
|
|
<a class="delete-dependency-button poping up ci muted" data-id="{{.Issue.ID}}" data-type="blocking" data-content="{{$.i18n.Tr "repo.issues.dependency.remove_info"}}" data-inverted="">
|
|
{{svg "octicon-trash" 16}}
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .BlockedByDependencies}}
|
|
<span class="text poping up" data-content="{{if .Issue.IsPull}}{{.i18n.Tr "repo.issues.dependency.pr_closing_blockedby"}}{{else}}{{.i18n.Tr "repo.issues.dependency.issue_closing_blockedby"}}{{end}}">
|
|
<strong>{{.i18n.Tr "repo.issues.dependency.blocked_by_short"}}</strong>
|
|
</span>
|
|
<div class="ui relaxed divided list">
|
|
{{range .BlockedByDependencies}}
|
|
<div class="item dependency{{if .Issue.IsClosed}} is-closed{{end}} df ac sb">
|
|
<div class="item-left df jc fc f1">
|
|
<a class="title" href="{{.Issue.Link}}">
|
|
#{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}
|
|
</a>
|
|
<div class="text small">
|
|
{{.Repository.OwnerName}}/{{.Repository.Name}}
|
|
</div>
|
|
</div>
|
|
<div class="item-right df ac">
|
|
{{if and $.CanCreateIssueDependencies (not $.Repository.IsArchived)}}
|
|
<a class="delete-dependency-button poping up ci muted" data-id="{{.Issue.ID}}" data-type="blockedBy" data-content="{{$.i18n.Tr "repo.issues.dependency.remove_info"}}" data-inverted="">
|
|
{{svg "octicon-trash" 16}}
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if and .CanCreateIssueDependencies (not .Repository.IsArchived)}}
|
|
<div>
|
|
<form method="POST" action="{{.Issue.Link}}/dependency/add" id="addDependencyForm">
|
|
{{$.CsrfTokenHtml}}
|
|
<div class="ui fluid action input">
|
|
<div class="ui search selection dropdown" id="new-dependency-drop-list" data-issue-id="{{.Issue.ID}}">
|
|
<input name="newDependency" type="hidden">
|
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
|
<input type="text" class="search">
|
|
<div class="default text">{{.i18n.Tr "repo.issues.dependency.add"}}</div>
|
|
</div>
|
|
<button class="ui green icon button">
|
|
{{svg "octicon-plus"}}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
{{if and .CanCreateIssueDependencies (not .Repository.IsArchived)}}
|
|
<input type="hidden" id="crossRepoSearch" value="{{.AllowCrossRepositoryDependencies}}">
|
|
|
|
<div class="ui basic modal remove-dependency">
|
|
<div class="ui icon header">
|
|
{{svg "octicon-trash"}}
|
|
{{.i18n.Tr "repo.issues.dependency.remove_header"}}
|
|
</div>
|
|
<div class="content">
|
|
<form method="POST" action="{{.Issue.Link}}/dependency/delete" id="removeDependencyForm">
|
|
{{$.CsrfTokenHtml}}
|
|
<input type="hidden" value="" name="removeDependencyID" id="removeDependencyID"/>
|
|
<input type="hidden" value="" name="dependencyType" id="dependencyType"/>
|
|
</form>
|
|
<p>{{if .Issue.IsPull}}
|
|
{{.i18n.Tr "repo.issues.dependency.pr_remove_text"}}
|
|
{{else}}
|
|
{{.i18n.Tr "repo.issues.dependency.issue_remove_text"}}
|
|
{{end}}</p>
|
|
</div>
|
|
<div class="actions">
|
|
<div class="ui red cancel inverted button">
|
|
{{svg "octicon-x"}}
|
|
{{.i18n.Tr "repo.issues.dependency.cancel"}}
|
|
</div>
|
|
<div class="ui green ok inverted button">
|
|
{{svg "octicon-check"}}
|
|
{{.i18n.Tr "repo.issues.dependency.remove"}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
|
|
{{if and .IsRepoAdmin (not .Repository.IsArchived)}}
|
|
<div class="ui divider"></div>
|
|
<div class="ui watching">
|
|
<button class="fluid ui show-modal button {{if .Issue.IsLocked }} negative {{end}}" data-modal="#lock">
|
|
{{if .Issue.IsLocked}}
|
|
{{svg "octicon-key"}}
|
|
{{.i18n.Tr "repo.issues.unlock"}}
|
|
{{else}}
|
|
{{svg "octicon-lock"}}
|
|
{{.i18n.Tr "repo.issues.lock"}}
|
|
{{end}}
|
|
</button>
|
|
</div>
|
|
<div class="ui tiny modal" id="lock">
|
|
<div class="header">
|
|
{{ if .Issue.IsLocked }}
|
|
{{.i18n.Tr "repo.issues.unlock.title"}}
|
|
{{else}}
|
|
{{.i18n.Tr "repo.issues.lock.title"}}
|
|
{{end}}
|
|
</div>
|
|
<div class="content">
|
|
<div class="ui warning message text left">
|
|
{{ if .Issue.IsLocked }}
|
|
{{.i18n.Tr "repo.issues.unlock.notice_1"}}<br>
|
|
{{.i18n.Tr "repo.issues.unlock.notice_2"}}<br>
|
|
{{else}}
|
|
{{.i18n.Tr "repo.issues.lock.notice_1"}}<br>
|
|
{{.i18n.Tr "repo.issues.lock.notice_2"}}<br>
|
|
{{.i18n.Tr "repo.issues.lock.notice_3"}}<br>
|
|
{{end}}
|
|
</div>
|
|
|
|
<form class="ui form" action="{{.Issue.Link}}{{ if .Issue.IsLocked }}/unlock{{else}}/lock{{end}}"
|
|
method="post">
|
|
{{.CsrfTokenHtml}}
|
|
|
|
{{ if not .Issue.IsLocked }}
|
|
<div class="field">
|
|
<strong> {{ .i18n.Tr "repo.issues.lock.reason" }} </strong>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<div class="ui fluid dropdown selection" tabindex="0">
|
|
|
|
<select name="reason">
|
|
<option value=""> </option>
|
|
{{range .LockReasons}}
|
|
<option value="{{.}}">{{.}}</option>
|
|
{{end}}
|
|
</select>
|
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
|
|
|
<div class="default text"> </div>
|
|
|
|
<div class="menu transition hidden" tabindex="-1" style="display: block !important;">
|
|
{{range .LockReasons}}
|
|
<div class="item" data-value="{{.}}">{{.}}</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="text right actions">
|
|
<div class="ui cancel button">{{.i18n.Tr "settings.cancel"}}</div>
|
|
<button class="ui red button">
|
|
{{ if .Issue.IsLocked }}
|
|
{{.i18n.Tr "repo.issues.unlock_confirm"}}
|
|
{{else}}
|
|
{{.i18n.Tr "repo.issues.lock_confirm"}}
|
|
{{end}}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|