mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-18 00:01:32 -04:00
Compare commits
4 Commits
79f7329971
...
fba7150ca9
Author | SHA1 | Date | |
---|---|---|---|
|
fba7150ca9 | ||
|
f1fe102c8c | ||
|
c802c46a9b | ||
|
9a3de436f4 |
@ -358,12 +358,21 @@ func applyMentionedCondition(sess *xorm.Session, mentionedID int64) *xorm.Sessio
|
||||
}
|
||||
|
||||
func applyReviewRequestedCondition(sess *xorm.Session, reviewRequestedID int64) *xorm.Session {
|
||||
return sess.Join("INNER", []string{"review", "r"}, "issue.id = r.issue_id").
|
||||
And("issue.poster_id <> ?", reviewRequestedID).
|
||||
And("r.type = ?", ReviewTypeRequest).
|
||||
And("r.reviewer_id = ? and r.id in (select max(id) from review where issue_id = r.issue_id and reviewer_id = r.reviewer_id and type in (?, ?, ?))"+
|
||||
" or r.reviewer_team_id in (select team_id from team_user where uid = ?)",
|
||||
reviewRequestedID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, reviewRequestedID)
|
||||
existInTeamQuery := builder.Select("team_user.team_id").
|
||||
From("team_user").
|
||||
Where(builder.Eq{"team_user.uid": reviewRequestedID})
|
||||
|
||||
subQuery := builder.Select("review.issue_id").
|
||||
From("review").
|
||||
Where(builder.And(
|
||||
builder.In("review.type", []ReviewType{ReviewTypeRequest, ReviewTypeReject, ReviewTypeApprove}),
|
||||
builder.Or(
|
||||
builder.Eq{"review.reviewer_id": reviewRequestedID},
|
||||
builder.In("review.reviewer_team_id", existInTeamQuery),
|
||||
),
|
||||
))
|
||||
return sess.Where("issue.poster_id <> ?", reviewRequestedID).
|
||||
And(builder.In("issue.id", subQuery))
|
||||
}
|
||||
|
||||
func applyReviewedCondition(sess *xorm.Session, reviewedID int64) *xorm.Session {
|
||||
|
@ -33,6 +33,11 @@ func (su *StringUtils) Join(a []string, sep string) string {
|
||||
return strings.Join(a, sep)
|
||||
}
|
||||
|
||||
func (su *StringUtils) Cut(s, sep string) []any {
|
||||
before, after, found := strings.Cut(s, sep)
|
||||
return []any{before, after, found}
|
||||
}
|
||||
|
||||
func (su *StringUtils) EllipsisString(s string, max int) string {
|
||||
return base.EllipsisString(s, max)
|
||||
}
|
||||
|
@ -1,29 +1,34 @@
|
||||
{{- /* og:description - a one to two sentence description of your object, maybe it only needs at most 300 bytes */ -}}
|
||||
{{if .PageIsUserProfile}}
|
||||
<meta property="og:title" content="{{.ContextUser.DisplayName}}">
|
||||
<meta property="og:type" content="profile">
|
||||
<meta property="og:image" content="{{.ContextUser.AvatarLink ctx}}">
|
||||
<meta property="og:url" content="{{.ContextUser.HTMLURL}}">
|
||||
{{if .ContextUser.Description}}
|
||||
<meta property="og:description" content="{{.ContextUser.Description}}">
|
||||
<meta property="og:description" content="{{StringUtils.EllipsisString .ContextUser.Description 300}}">
|
||||
{{end}}
|
||||
{{else if .Repository}}
|
||||
{{if .Issue}}
|
||||
<meta property="og:title" content="{{.Issue.Title}}">
|
||||
<meta property="og:url" content="{{.Issue.HTMLURL}}">
|
||||
{{if .Issue.Content}}
|
||||
<meta property="og:description" content="{{.Issue.Content}}">
|
||||
<meta property="og:description" content="{{StringUtils.EllipsisString .Issue.Content 300}}">
|
||||
{{end}}
|
||||
{{else if or .PageIsDiff .IsViewFile}}
|
||||
<meta property="og:title" content="{{.Title}}">
|
||||
<meta property="og:url" content="{{AppUrl}}{{.Link}}">
|
||||
{{if and .PageIsDiff (IsMultilineCommitMessage .Commit.Message)}}
|
||||
<meta property="og:description" content="{{RenderCommitBody $.Context .Commit.Message $.RepoLink $.Repository.ComposeMetas}}">
|
||||
{{if .PageIsDiff}}
|
||||
{{- $commitMessageParts := StringUtils.Cut .Commit.Message "\n" -}}
|
||||
{{- $commitMessageBody := index $commitMessageParts 1 -}}
|
||||
{{- if $commitMessageBody -}}
|
||||
<meta property="og:description" content="{{StringUtils.EllipsisString $commitMessageBody 300}}">
|
||||
{{- end -}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
<meta property="og:title" content="{{.Repository.Name}}">
|
||||
<meta property="og:url" content="{{.Repository.HTMLURL}}">
|
||||
{{if .Repository.Description}}
|
||||
<meta property="og:description" content="{{.Repository.Description}}">
|
||||
<meta property="og:description" content="{{StringUtils.EllipsisString .Repository.Description 300}}">
|
||||
{{end}}
|
||||
{{end}}
|
||||
<meta property="og:type" content="object">
|
||||
|
@ -41,28 +41,18 @@
|
||||
{{$class = (printf "%s%s" $class " isWarning")}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{$commitShaLink := ""}}
|
||||
{{if $.PageIsWiki}}
|
||||
<a href="{{$commitRepoLink}}/wiki/commit/{{.ID}}" rel="nofollow" class="{{$class}}">
|
||||
{{$commitShaLink = (printf "%s/wiki/commit/%s" $commitRepoLink (PathEscape .ID.String))}}
|
||||
{{else if $.PageIsPullCommits}}
|
||||
<a href="{{$commitRepoLink}}/pulls/{{$.Issue.Index}}/commits/{{.ID}}" rel="nofollow" class="{{$class}}">
|
||||
{{$commitShaLink = (printf "%s/pulls/%d/commits/%s" $commitRepoLink $.Issue.Index (PathEscape .ID.String))}}
|
||||
{{else if $.Reponame}}
|
||||
<a href="{{$commitRepoLink}}/commit/{{.ID}}" rel="nofollow" class="{{$class}}">
|
||||
{{else}}
|
||||
<span class="{{$class}}">
|
||||
{{$commitShaLink = (printf "%s/commit/%s" $commitRepoLink (PathEscape .ID.String))}}
|
||||
{{end}}
|
||||
<a {{if $commitShaLink}}href="{{$commitShaLink}}"{{end}} class="{{$class}}">
|
||||
<span class="shortsha">{{ShortSha .ID.String}}</span>
|
||||
{{if .Signature}}
|
||||
{{template "repo/shabox_badge" dict "root" $ "verification" .Verification}}
|
||||
{{end}}
|
||||
{{if $.PageIsWiki}}
|
||||
</a>
|
||||
{{else if $.PageIsPullCommits}}
|
||||
</a>
|
||||
{{else if $.Reponame}}
|
||||
</a>
|
||||
{{else}}
|
||||
</span>
|
||||
{{end}}
|
||||
{{if .Signature}}{{template "repo/shabox_badge" dict "root" $ "verification" .Verification}}{{end}}
|
||||
</a>
|
||||
</td>
|
||||
<td class="message">
|
||||
<span class="message-wrapper">
|
||||
@ -78,7 +68,7 @@
|
||||
{{end}}
|
||||
{{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses "root" $}}
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
<pre class="commit-body gt-hidden">{{RenderCommitBody $.Context .Message $commitRepoLink $.Repository.ComposeMetas}}</pre>
|
||||
<pre class="commit-body gt-m-0 gt-hidden">{{RenderCommitBody $.Context .Message $commitRepoLink $.Repository.ComposeMetas}}</pre>
|
||||
{{end}}
|
||||
</td>
|
||||
{{if .Committer}}
|
||||
|
@ -24,7 +24,7 @@
|
||||
<a href="{{$.RepoLink}}/commit/{{$commit.Rev|PathEscape}}" rel="nofollow" class="{{$class}}">
|
||||
<span class="shortsha">{{ShortSha $commit.Commit.ID.String}}</span>
|
||||
{{- if $commit.Commit.Signature -}}
|
||||
<span class="shortsha-pad"></span>{{template "repo/shabox_badge" dict "root" $ "verification" $commit.Verification}}
|
||||
{{template "repo/shabox_badge" dict "root" $ "verification" $commit.Verification}}
|
||||
{{- end -}}
|
||||
</a>
|
||||
</span>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="ui active tiny slow centered inline">…</div>
|
||||
{{else}}
|
||||
{{if .LatestCommitUser}}
|
||||
{{ctx.AvatarUtils.Avatar .LatestCommitUser 24}}
|
||||
{{ctx.AvatarUtils.Avatar .LatestCommitUser 24 "gt-mr-2"}}
|
||||
{{if .LatestCommitUser.FullName}}
|
||||
<a class="muted author-wrapper" title="{{.LatestCommitUser.FullName}}" href="{{.LatestCommitUser.HomeLink}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
|
||||
{{else}}
|
||||
@ -14,7 +14,7 @@
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if .LatestCommit.Author}}
|
||||
{{ctx.AvatarUtils.AvatarByEmail .LatestCommit.Author.Email .LatestCommit.Author.Name 24}}
|
||||
{{ctx.AvatarUtils.AvatarByEmail .LatestCommit.Author.Email .LatestCommit.Author.Name 24 "gt-mr-2"}}
|
||||
<span class="author-wrapper" title="{{.LatestCommit.Author.Name}}"><strong>{{.LatestCommit.Author.Name}}</strong></span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
@ -1308,9 +1308,13 @@ img.ui.avatar,
|
||||
.ui .sha.label {
|
||||
font-family: var(--fonts-monospace);
|
||||
font-size: 13px;
|
||||
padding: 6px 10px 4px;
|
||||
font-weight: var(--font-weight-normal);
|
||||
margin: 0 6px;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.ui .sha.label .shortsha {
|
||||
display: inline-block; /* not sure whether it is still needed */
|
||||
}
|
||||
|
||||
.ui .button.copy-commit-sha {
|
||||
|
@ -123,14 +123,6 @@
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
#git-graph-container #rev-list .sha.label .shortsha {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#git-graph-container #rev-list .sha.label .shortsha-pad {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#git-graph-container #rev-list .sha.label .ui.detail.icon.button {
|
||||
padding-top: 3px;
|
||||
margin-top: -5px;
|
||||
|
@ -245,15 +245,9 @@
|
||||
}
|
||||
|
||||
.repository.file.list #repo-files-table thead th {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 5px;
|
||||
font-weight: var(--font-weight-normal);
|
||||
}
|
||||
|
||||
.repository.file.list #repo-files-table thead .ui.avatar {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.repository.file.list #repo-files-table tbody .svg {
|
||||
margin-left: 3px;
|
||||
margin-right: 5px;
|
||||
@ -891,11 +885,6 @@
|
||||
background: var(--color-red-badge-bg);
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isWarning .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isWarning:hover {
|
||||
background: var(--color-red-badge-hover-bg) !important;
|
||||
}
|
||||
@ -905,11 +894,6 @@
|
||||
background: var(--color-green-badge-bg);
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerified .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerified:hover {
|
||||
background: var(--color-green-badge-hover-bg) !important;
|
||||
}
|
||||
@ -919,11 +903,6 @@
|
||||
background: var(--color-yellow-badge-bg);
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUntrusted .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUntrusted:hover {
|
||||
background: var(--color-yellow-badge-hover-bg) !important;
|
||||
}
|
||||
@ -933,11 +912,6 @@
|
||||
background: var(--color-orange-badge-bg);
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUnmatched .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUnmatched:hover {
|
||||
background: var(--color-orange-badge-hover-bg) !important;
|
||||
}
|
||||
@ -1387,14 +1361,6 @@
|
||||
background: var(--color-red-badge-bg);
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isWarning .shortsha,
|
||||
.repository #repo-files-table .sha.label.isSigned.isWarning .shortsha,
|
||||
.repository #rev-list .sha.label.isSigned.isWarning .shortsha,
|
||||
.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isWarning .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isWarning .detail.icon,
|
||||
.repository #repo-files-table .sha.label.isSigned.isWarning .detail.icon,
|
||||
.repository #rev-list .sha.label.isSigned.isWarning .detail.icon,
|
||||
@ -1418,14 +1384,6 @@
|
||||
background: var(--color-green-badge-bg);
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isVerified .shortsha,
|
||||
.repository #repo-files-table .sha.label.isSigned.isVerified .shortsha,
|
||||
.repository #rev-list .sha.label.isSigned.isVerified .shortsha,
|
||||
.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerified .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isVerified .detail.icon,
|
||||
.repository #repo-files-table .sha.label.isSigned.isVerified .detail.icon,
|
||||
.repository #rev-list .sha.label.isSigned.isVerified .detail.icon,
|
||||
@ -1449,14 +1407,6 @@
|
||||
background: var(--color-yellow-badge-bg);
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUntrusted .shortsha,
|
||||
.repository #repo-files-table .sha.label.isSigned.isVerifiedUntrusted .shortsha,
|
||||
.repository #rev-list .sha.label.isSigned.isVerifiedUntrusted .shortsha,
|
||||
.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUntrusted .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUntrusted .detail.icon,
|
||||
.repository #repo-files-table .sha.label.isSigned.isVerifiedUntrusted .detail.icon,
|
||||
.repository #rev-list .sha.label.isSigned.isVerifiedUntrusted .detail.icon,
|
||||
@ -1480,14 +1430,6 @@
|
||||
background: var(--color-orange-badge-bg);
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUnmatched .shortsha,
|
||||
.repository #repo-files-table .sha.label.isSigned.isVerifiedUnmatched .shortsha,
|
||||
.repository #rev-list .sha.label.isSigned.isVerifiedUnmatched .shortsha,
|
||||
.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUnmatched .shortsha {
|
||||
display: inline-block;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUnmatched .detail.icon,
|
||||
.repository #repo-files-table .sha.label.isSigned.isVerifiedUnmatched .detail.icon,
|
||||
.repository #rev-list .sha.label.isSigned.isVerifiedUnmatched .detail.icon,
|
||||
@ -2691,11 +2633,6 @@ tbody.commit-list {
|
||||
line-height: initial;
|
||||
}
|
||||
|
||||
/* commit history list */
|
||||
.repository:not(.diff) .commit-body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* PR-comment */
|
||||
.repository:not(.diff) .timeline-item .commit-body {
|
||||
margin-left: 40px;
|
||||
|
@ -2,17 +2,6 @@
|
||||
Please also update the template file above if this vue is modified.
|
||||
action status accepted: success, skipped, waiting, blocked, running, failure, cancelled, unknown
|
||||
-->
|
||||
<template>
|
||||
<span class="gt-df gt-ac" :data-tooltip-content="localeStatus" v-if="status">
|
||||
<SvgIcon name="octicon-check-circle-fill" class="text green" :size="size" :class-name="className" v-if="status === 'success'"/>
|
||||
<SvgIcon name="octicon-skip" class="text grey" :size="size" :class-name="className" v-else-if="status === 'skipped'"/>
|
||||
<SvgIcon name="octicon-clock" class="text yellow" :size="size" :class-name="className" v-else-if="status === 'waiting'"/>
|
||||
<SvgIcon name="octicon-blocked" class="text yellow" :size="size" :class-name="className" v-else-if="status === 'blocked'"/>
|
||||
<SvgIcon name="octicon-meter" class="text yellow" :size="size" :class-name="'job-status-rotate ' + className" v-else-if="status === 'running'"/>
|
||||
<SvgIcon name="octicon-x-circle-fill" class="text red" :size="size" v-else-if="['failure', 'cancelled', 'unknown'].includes(status)"/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {SvgIcon} from '../svg.js';
|
||||
|
||||
@ -38,3 +27,13 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span class="gt-df gt-ac" :data-tooltip-content="localeStatus" v-if="status">
|
||||
<SvgIcon name="octicon-check-circle-fill" class="text green" :size="size" :class-name="className" v-if="status === 'success'"/>
|
||||
<SvgIcon name="octicon-skip" class="text grey" :size="size" :class-name="className" v-else-if="status === 'skipped'"/>
|
||||
<SvgIcon name="octicon-clock" class="text yellow" :size="size" :class-name="className" v-else-if="status === 'waiting'"/>
|
||||
<SvgIcon name="octicon-blocked" class="text yellow" :size="size" :class-name="className" v-else-if="status === 'blocked'"/>
|
||||
<SvgIcon name="octicon-meter" class="text yellow" :size="size" :class-name="'job-status-rotate ' + className" v-else-if="status === 'running'"/>
|
||||
<SvgIcon name="octicon-x-circle-fill" class="text red" :size="size" v-else-if="['failure', 'cancelled', 'unknown'].includes(status)"/>
|
||||
</span>
|
||||
</template>
|
||||
|
@ -1,17 +1,3 @@
|
||||
<template>
|
||||
<div class="total-contributions">
|
||||
{{ locale.contributions_in_the_last_12_months }}
|
||||
</div>
|
||||
<calendar-heatmap
|
||||
:locale="locale"
|
||||
:no-data-text="locale.no_contributions"
|
||||
:tooltip-unit="locale.contributions"
|
||||
:end-date="endDate"
|
||||
:values="values"
|
||||
:range-color="colorRange"
|
||||
@day-click="handleDayClick($event)"
|
||||
/>
|
||||
</template>
|
||||
<script>
|
||||
import {CalendarHeatmap} from 'vue3-calendar-heatmap';
|
||||
|
||||
@ -67,3 +53,17 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="total-contributions">
|
||||
{{ locale.contributions_in_the_last_12_months }}
|
||||
</div>
|
||||
<calendar-heatmap
|
||||
:locale="locale"
|
||||
:no-data-text="locale.no_contributions"
|
||||
:tooltip-unit="locale.contributions"
|
||||
:end-date="endDate"
|
||||
:values="values"
|
||||
:range-color="colorRange"
|
||||
@day-click="handleDayClick($event)"
|
||||
/>
|
||||
</template>
|
||||
|
@ -1,28 +1,3 @@
|
||||
<template>
|
||||
<div ref="root">
|
||||
<div v-if="loading" class="ui active centered inline loader"/>
|
||||
<div v-if="!loading && issue !== null">
|
||||
<p><small>{{ issue.repository.full_name }} on {{ createdAt }}</small></p>
|
||||
<p><svg-icon :name="icon" :class="['text', color]"/> <strong>{{ issue.title }}</strong> #{{ issue.number }}</p>
|
||||
<p>{{ body }}</p>
|
||||
<div>
|
||||
<div
|
||||
v-for="label in labels"
|
||||
:key="label.name"
|
||||
class="ui label"
|
||||
:style="{ color: label.textColor, backgroundColor: label.color }"
|
||||
>
|
||||
{{ label.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!loading && issue === null">
|
||||
<p><small>{{ i18nErrorOccurred }}</small></p>
|
||||
<p>{{ i18nErrorMessage }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
import {SvgIcon} from '../svg.js';
|
||||
@ -115,3 +90,27 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div ref="root">
|
||||
<div v-if="loading" class="ui active centered inline loader"/>
|
||||
<div v-if="!loading && issue !== null">
|
||||
<p><small>{{ issue.repository.full_name }} on {{ createdAt }}</small></p>
|
||||
<p><svg-icon :name="icon" :class="['text', color]"/> <strong>{{ issue.title }}</strong> #{{ issue.number }}</p>
|
||||
<p>{{ body }}</p>
|
||||
<div>
|
||||
<div
|
||||
v-for="label in labels"
|
||||
:key="label.name"
|
||||
class="ui label"
|
||||
:style="{ color: label.textColor, backgroundColor: label.color }"
|
||||
>
|
||||
{{ label.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!loading && issue === null">
|
||||
<p><small>{{ i18nErrorOccurred }}</small></p>
|
||||
<p>{{ i18nErrorMessage }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,152 +1,3 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="!isOrganization" class="ui two item menu">
|
||||
<a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{ textRepository }}</a>
|
||||
<a :class="{item: true, active: tab === 'organizations'}" @click="changeTab('organizations')">{{ textOrganization }}</a>
|
||||
</div>
|
||||
<div v-show="tab === 'repos'" class="ui tab active list dashboard-repos">
|
||||
<h4 class="ui top attached header gt-df gt-ac">
|
||||
<div class="gt-f1 gt-df gt-ac">
|
||||
{{ textMyRepos }}
|
||||
<span class="ui grey label gt-ml-3">{{ reposTotalCount }}</span>
|
||||
</div>
|
||||
<a class="gt-df gt-ac muted" :href="subUrl + '/repo/create' + (isOrganization ? '?org=' + organizationId : '')" :data-tooltip-content="textNewRepo">
|
||||
<svg-icon name="octicon-plus"/>
|
||||
</a>
|
||||
</h4>
|
||||
<div class="ui attached segment repos-search">
|
||||
<div class="ui fluid action left icon input" :class="{loading: isLoading}">
|
||||
<input type="search" spellcheck="false" maxlength="255" @input="changeReposFilter(reposFilter)" v-model="searchQuery" ref="search" @keydown="reposFilterKeyControl" :placeholder="textSearchRepos">
|
||||
<i class="icon"><svg-icon name="octicon-search" :size="16"/></i>
|
||||
<div class="ui dropdown icon button" :title="textFilter">
|
||||
<svg-icon name="octicon-filter" :size="16"/>
|
||||
<div class="menu">
|
||||
<a class="item" @click="toggleArchivedFilter()">
|
||||
<div class="ui checkbox" ref="checkboxArchivedFilter" :title="checkboxArchivedFilterTitle">
|
||||
<!--the "hidden" is necessary to make the checkbox work without Fomantic UI js,
|
||||
otherwise if the "input" handles click event for intermediate status, it breaks the internal state-->
|
||||
<input type="checkbox" class="hidden" v-bind.prop="checkboxArchivedFilterProps">
|
||||
<label>
|
||||
<svg-icon name="octicon-archive" :size="16" class-name="gt-mr-2"/>
|
||||
{{ textShowArchived }}
|
||||
</label>
|
||||
</div>
|
||||
</a>
|
||||
<a class="item" @click="togglePrivateFilter()">
|
||||
<div class="ui checkbox" ref="checkboxPrivateFilter" :title="checkboxPrivateFilterTitle">
|
||||
<input type="checkbox" class="hidden" v-bind.prop="checkboxPrivateFilterProps">
|
||||
<label>
|
||||
<svg-icon name="octicon-lock" :size="16" class-name="gt-mr-2"/>
|
||||
{{ textShowPrivate }}
|
||||
</label>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui secondary tiny pointing borderless menu center grid repos-filter">
|
||||
<a class="item" :class="{active: reposFilter === 'all'}" @click="changeReposFilter('all')">
|
||||
{{ textAll }}
|
||||
<div v-show="reposFilter === 'all'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'sources'}" @click="changeReposFilter('sources')">
|
||||
{{ textSources }}
|
||||
<div v-show="reposFilter === 'sources'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'forks'}" @click="changeReposFilter('forks')">
|
||||
{{ textForks }}
|
||||
<div v-show="reposFilter === 'forks'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'mirrors'}" @click="changeReposFilter('mirrors')" v-if="isMirrorsEnabled">
|
||||
{{ textMirrors }}
|
||||
<div v-show="reposFilter === 'mirrors'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'collaborative'}" @click="changeReposFilter('collaborative')">
|
||||
{{ textCollaborative }}
|
||||
<div v-show="reposFilter === 'collaborative'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="repos.length" class="ui attached table segment gt-rounded-bottom">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li class="gt-df gt-ac gt-py-3" v-for="repo, index in repos" :class="{'active': index === activeIndex}" :key="repo.id">
|
||||
<a class="repo-list-link muted" :href="repo.link">
|
||||
<svg-icon :name="repoIcon(repo)" :size="16" class-name="repo-list-icon"/>
|
||||
<div class="text truncate">{{ repo.full_name }}</div>
|
||||
<div v-if="repo.archived">
|
||||
<svg-icon name="octicon-archive" :size="16"/>
|
||||
</div>
|
||||
</a>
|
||||
<a class="gt-df gt-ac" v-if="repo.latest_commit_status_state" :href="repo.latest_commit_status_state_link" :data-tooltip-content="repo.locale_latest_commit_status_state">
|
||||
<!-- the commit status icon logic is taken from templates/repo/commit_status.tmpl -->
|
||||
<svg-icon :name="statusIcon(repo.latest_commit_status_state)" :class-name="'gt-ml-3 commit-status icon text ' + statusColor(repo.latest_commit_status_state)" :size="16"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-if="showMoreReposLink" class="center gt-py-3 gt-border-secondary-top">
|
||||
<div class="ui borderless pagination menu narrow">
|
||||
<a
|
||||
class="item navigation gt-py-2" :class="{'disabled': page === 1}"
|
||||
@click="changePage(1)" :title="textFirstPage"
|
||||
>
|
||||
<svg-icon name="gitea-double-chevron-left" :size="16" class-name="gt-mr-2"/>
|
||||
</a>
|
||||
<a
|
||||
class="item navigation gt-py-2" :class="{'disabled': page === 1}"
|
||||
@click="changePage(page - 1)" :title="textPreviousPage"
|
||||
>
|
||||
<svg-icon name="octicon-chevron-left" :size="16" clsas-name="gt-mr-2"/>
|
||||
</a>
|
||||
<a class="active item gt-py-2">{{ page }}</a>
|
||||
<a
|
||||
class="item navigation" :class="{'disabled': page === finalPage}"
|
||||
@click="changePage(page + 1)" :title="textNextPage"
|
||||
>
|
||||
<svg-icon name="octicon-chevron-right" :size="16" class-name="gt-ml-2"/>
|
||||
</a>
|
||||
<a
|
||||
class="item navigation gt-py-2" :class="{'disabled': page === finalPage}"
|
||||
@click="changePage(finalPage)" :title="textLastPage"
|
||||
>
|
||||
<svg-icon name="gitea-double-chevron-right" :size="16" class-name="gt-ml-2"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isOrganization" v-show="tab === 'organizations'" class="ui tab active list dashboard-orgs">
|
||||
<h4 class="ui top attached header gt-df gt-ac">
|
||||
<div class="gt-f1 gt-df gt-ac">
|
||||
{{ textMyOrgs }}
|
||||
<span class="ui grey label gt-ml-3">{{ organizationsTotalCount }}</span>
|
||||
</div>
|
||||
<a class="gt-df gt-ac muted" v-if="canCreateOrganization" :href="subUrl + '/org/create'" :data-tooltip-content="textNewOrg">
|
||||
<svg-icon name="octicon-plus"/>
|
||||
</a>
|
||||
</h4>
|
||||
<div v-if="organizations.length" class="ui attached table segment gt-rounded-bottom">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li class="gt-df gt-ac gt-py-3" v-for="org in organizations" :key="org.name">
|
||||
<a class="repo-list-link muted" :href="subUrl + '/' + encodeURIComponent(org.name)">
|
||||
<svg-icon name="octicon-organization" :size="16" class-name="repo-list-icon"/>
|
||||
<div class="text truncate">{{ org.name }}</div>
|
||||
<div><!-- div to prevent underline of label on hover -->
|
||||
<span class="ui tiny basic label" v-if="org.org_visibility !== 'public'">
|
||||
{{ org.org_visibility === 'limited' ? textOrgVisibilityLimited: textOrgVisibilityPrivate }}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="text light grey gt-df gt-ac gt-ml-3">
|
||||
{{ org.num_repos }}
|
||||
<svg-icon name="octicon-repo" :size="16" class-name="gt-ml-2 gt-mt-1"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApp, nextTick} from 'vue';
|
||||
import $ from 'jquery';
|
||||
@ -485,8 +336,155 @@ export function initDashboardRepoList() {
|
||||
}
|
||||
|
||||
export default sfc; // activate the IDE's Vue plugin
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="!isOrganization" class="ui two item menu">
|
||||
<a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{ textRepository }}</a>
|
||||
<a :class="{item: true, active: tab === 'organizations'}" @click="changeTab('organizations')">{{ textOrganization }}</a>
|
||||
</div>
|
||||
<div v-show="tab === 'repos'" class="ui tab active list dashboard-repos">
|
||||
<h4 class="ui top attached header gt-df gt-ac">
|
||||
<div class="gt-f1 gt-df gt-ac">
|
||||
{{ textMyRepos }}
|
||||
<span class="ui grey label gt-ml-3">{{ reposTotalCount }}</span>
|
||||
</div>
|
||||
<a class="gt-df gt-ac muted" :href="subUrl + '/repo/create' + (isOrganization ? '?org=' + organizationId : '')" :data-tooltip-content="textNewRepo">
|
||||
<svg-icon name="octicon-plus"/>
|
||||
</a>
|
||||
</h4>
|
||||
<div class="ui attached segment repos-search">
|
||||
<div class="ui fluid action left icon input" :class="{loading: isLoading}">
|
||||
<input type="search" spellcheck="false" maxlength="255" @input="changeReposFilter(reposFilter)" v-model="searchQuery" ref="search" @keydown="reposFilterKeyControl" :placeholder="textSearchRepos">
|
||||
<i class="icon"><svg-icon name="octicon-search" :size="16"/></i>
|
||||
<div class="ui dropdown icon button" :title="textFilter">
|
||||
<svg-icon name="octicon-filter" :size="16"/>
|
||||
<div class="menu">
|
||||
<a class="item" @click="toggleArchivedFilter()">
|
||||
<div class="ui checkbox" ref="checkboxArchivedFilter" :title="checkboxArchivedFilterTitle">
|
||||
<!--the "hidden" is necessary to make the checkbox work without Fomantic UI js,
|
||||
otherwise if the "input" handles click event for intermediate status, it breaks the internal state-->
|
||||
<input type="checkbox" class="hidden" v-bind.prop="checkboxArchivedFilterProps">
|
||||
<label>
|
||||
<svg-icon name="octicon-archive" :size="16" class-name="gt-mr-2"/>
|
||||
{{ textShowArchived }}
|
||||
</label>
|
||||
</div>
|
||||
</a>
|
||||
<a class="item" @click="togglePrivateFilter()">
|
||||
<div class="ui checkbox" ref="checkboxPrivateFilter" :title="checkboxPrivateFilterTitle">
|
||||
<input type="checkbox" class="hidden" v-bind.prop="checkboxPrivateFilterProps">
|
||||
<label>
|
||||
<svg-icon name="octicon-lock" :size="16" class-name="gt-mr-2"/>
|
||||
{{ textShowPrivate }}
|
||||
</label>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui secondary tiny pointing borderless menu center grid repos-filter">
|
||||
<a class="item" :class="{active: reposFilter === 'all'}" @click="changeReposFilter('all')">
|
||||
{{ textAll }}
|
||||
<div v-show="reposFilter === 'all'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'sources'}" @click="changeReposFilter('sources')">
|
||||
{{ textSources }}
|
||||
<div v-show="reposFilter === 'sources'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'forks'}" @click="changeReposFilter('forks')">
|
||||
{{ textForks }}
|
||||
<div v-show="reposFilter === 'forks'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'mirrors'}" @click="changeReposFilter('mirrors')" v-if="isMirrorsEnabled">
|
||||
{{ textMirrors }}
|
||||
<div v-show="reposFilter === 'mirrors'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
<a class="item" :class="{active: reposFilter === 'collaborative'}" @click="changeReposFilter('collaborative')">
|
||||
{{ textCollaborative }}
|
||||
<div v-show="reposFilter === 'collaborative'" class="ui circular mini grey label">{{ repoTypeCount }}</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="repos.length" class="ui attached table segment gt-rounded-bottom">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li class="gt-df gt-ac gt-py-3" v-for="repo, index in repos" :class="{'active': index === activeIndex}" :key="repo.id">
|
||||
<a class="repo-list-link muted" :href="repo.link">
|
||||
<svg-icon :name="repoIcon(repo)" :size="16" class-name="repo-list-icon"/>
|
||||
<div class="text truncate">{{ repo.full_name }}</div>
|
||||
<div v-if="repo.archived">
|
||||
<svg-icon name="octicon-archive" :size="16"/>
|
||||
</div>
|
||||
</a>
|
||||
<a class="gt-df gt-ac" v-if="repo.latest_commit_status_state" :href="repo.latest_commit_status_state_link" :data-tooltip-content="repo.locale_latest_commit_status_state">
|
||||
<!-- the commit status icon logic is taken from templates/repo/commit_status.tmpl -->
|
||||
<svg-icon :name="statusIcon(repo.latest_commit_status_state)" :class-name="'gt-ml-3 commit-status icon text ' + statusColor(repo.latest_commit_status_state)" :size="16"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-if="showMoreReposLink" class="center gt-py-3 gt-border-secondary-top">
|
||||
<div class="ui borderless pagination menu narrow">
|
||||
<a
|
||||
class="item navigation gt-py-2" :class="{'disabled': page === 1}"
|
||||
@click="changePage(1)" :title="textFirstPage"
|
||||
>
|
||||
<svg-icon name="gitea-double-chevron-left" :size="16" class-name="gt-mr-2"/>
|
||||
</a>
|
||||
<a
|
||||
class="item navigation gt-py-2" :class="{'disabled': page === 1}"
|
||||
@click="changePage(page - 1)" :title="textPreviousPage"
|
||||
>
|
||||
<svg-icon name="octicon-chevron-left" :size="16" clsas-name="gt-mr-2"/>
|
||||
</a>
|
||||
<a class="active item gt-py-2">{{ page }}</a>
|
||||
<a
|
||||
class="item navigation" :class="{'disabled': page === finalPage}"
|
||||
@click="changePage(page + 1)" :title="textNextPage"
|
||||
>
|
||||
<svg-icon name="octicon-chevron-right" :size="16" class-name="gt-ml-2"/>
|
||||
</a>
|
||||
<a
|
||||
class="item navigation gt-py-2" :class="{'disabled': page === finalPage}"
|
||||
@click="changePage(finalPage)" :title="textLastPage"
|
||||
>
|
||||
<svg-icon name="gitea-double-chevron-right" :size="16" class-name="gt-ml-2"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isOrganization" v-show="tab === 'organizations'" class="ui tab active list dashboard-orgs">
|
||||
<h4 class="ui top attached header gt-df gt-ac">
|
||||
<div class="gt-f1 gt-df gt-ac">
|
||||
{{ textMyOrgs }}
|
||||
<span class="ui grey label gt-ml-3">{{ organizationsTotalCount }}</span>
|
||||
</div>
|
||||
<a class="gt-df gt-ac muted" v-if="canCreateOrganization" :href="subUrl + '/org/create'" :data-tooltip-content="textNewOrg">
|
||||
<svg-icon name="octicon-plus"/>
|
||||
</a>
|
||||
</h4>
|
||||
<div v-if="organizations.length" class="ui attached table segment gt-rounded-bottom">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li class="gt-df gt-ac gt-py-3" v-for="org in organizations" :key="org.name">
|
||||
<a class="repo-list-link muted" :href="subUrl + '/' + encodeURIComponent(org.name)">
|
||||
<svg-icon name="octicon-organization" :size="16" class-name="repo-list-icon"/>
|
||||
<div class="text truncate">{{ org.name }}</div>
|
||||
<div><!-- div to prevent underline of label on hover -->
|
||||
<span class="ui tiny basic label" v-if="org.org_visibility !== 'public'">
|
||||
{{ org.org_visibility === 'limited' ? textOrgVisibilityLimited: textOrgVisibilityPrivate }}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="text light grey gt-df gt-ac gt-ml-3">
|
||||
{{ org.num_repos }}
|
||||
<svg-icon name="octicon-repo" :size="16" class-name="gt-ml-2 gt-mt-1"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
ul {
|
||||
list-style: none;
|
||||
|
@ -1,75 +1,3 @@
|
||||
<template>
|
||||
<div class="ui scrolling dropdown custom">
|
||||
<button
|
||||
class="ui basic button"
|
||||
id="diff-commit-list-expand"
|
||||
@click.stop="toggleMenu()"
|
||||
:data-tooltip-content="locale.filter_changes_by_commit"
|
||||
aria-haspopup="true"
|
||||
aria-controls="diff-commit-selector-menu"
|
||||
:aria-label="locale.filter_changes_by_commit"
|
||||
aria-activedescendant="diff-commit-list-show-all"
|
||||
>
|
||||
<svg-icon name="octicon-git-commit"/>
|
||||
</button>
|
||||
<div class="menu left transition" id="diff-commit-selector-menu" :class="{visible: menuVisible}" v-show="menuVisible" v-cloak :aria-expanded="menuVisible ? 'true': 'false'">
|
||||
<div class="loading-indicator is-loading" v-if="isLoading"/>
|
||||
<div v-if="!isLoading" class="vertical item gt-df gt-fc gt-gap-2" id="diff-commit-list-show-all" role="menuitem" @keydown.enter="showAllChanges()" @click="showAllChanges()">
|
||||
<div class="gt-ellipsis">
|
||||
{{ locale.show_all_commits }}
|
||||
</div>
|
||||
<div class="gt-ellipsis text light-2 gt-mb-0">
|
||||
{{ locale.stats_num_commits }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- only show the show changes since last review if there is a review AND we are commits ahead of the last review -->
|
||||
<div
|
||||
v-if="lastReviewCommitSha != null" role="menuitem"
|
||||
class="vertical item gt-df gt-fc gt-gap-2 gt-border-secondary-top"
|
||||
:class="{disabled: commitsSinceLastReview === 0}"
|
||||
@keydown.enter="changesSinceLastReviewClick()"
|
||||
@click="changesSinceLastReviewClick()"
|
||||
>
|
||||
<div class="gt-ellipsis">
|
||||
{{ locale.show_changes_since_your_last_review }}
|
||||
</div>
|
||||
<div class="gt-ellipsis text light-2">
|
||||
{{ commitsSinceLastReview }} commits
|
||||
</div>
|
||||
</div>
|
||||
<span v-if="!isLoading" class="info gt-border-secondary-top text light-2">{{ locale.select_commit_hold_shift_for_range }}</span>
|
||||
<template v-for="commit in commits" :key="commit.id">
|
||||
<div
|
||||
class="vertical item gt-df gt-gap-2 gt-border-secondary-top" role="menuitem"
|
||||
:class="{selection: commit.selected, hovered: commit.hovered}"
|
||||
@keydown.enter.exact="commitClicked(commit.id)"
|
||||
@keydown.enter.shift.exact="commitClickedShift(commit)"
|
||||
@mouseover.shift="highlight(commit)"
|
||||
@click.exact="commitClicked(commit.id)"
|
||||
@click.ctrl.exact="commitClicked(commit.id, true)"
|
||||
@click.meta.exact="commitClicked(commit.id, true)"
|
||||
@click.shift.exact.stop.prevent="commitClickedShift(commit)"
|
||||
>
|
||||
<div class="gt-f1 gt-df gt-fc gt-gap-2">
|
||||
<div class="gt-ellipsis commit-list-summary">
|
||||
{{ commit.summary }}
|
||||
</div>
|
||||
<div class="gt-ellipsis text light-2">
|
||||
{{ commit.committer_or_author_name }}
|
||||
<span class="text right">
|
||||
<relative-time class="time-since" prefix="" :datetime="commit.time" data-tooltip-content data-tooltip-interactive="true">{{ commit.time }}</relative-time>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gt-mono">
|
||||
{{ commit.short_sha }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {SvgIcon} from '../svg.js';
|
||||
|
||||
@ -259,6 +187,77 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="ui scrolling dropdown custom">
|
||||
<button
|
||||
class="ui basic button"
|
||||
id="diff-commit-list-expand"
|
||||
@click.stop="toggleMenu()"
|
||||
:data-tooltip-content="locale.filter_changes_by_commit"
|
||||
aria-haspopup="true"
|
||||
aria-controls="diff-commit-selector-menu"
|
||||
:aria-label="locale.filter_changes_by_commit"
|
||||
aria-activedescendant="diff-commit-list-show-all"
|
||||
>
|
||||
<svg-icon name="octicon-git-commit"/>
|
||||
</button>
|
||||
<div class="menu left transition" id="diff-commit-selector-menu" :class="{visible: menuVisible}" v-show="menuVisible" v-cloak :aria-expanded="menuVisible ? 'true': 'false'">
|
||||
<div class="loading-indicator is-loading" v-if="isLoading"/>
|
||||
<div v-if="!isLoading" class="vertical item gt-df gt-fc gt-gap-2" id="diff-commit-list-show-all" role="menuitem" @keydown.enter="showAllChanges()" @click="showAllChanges()">
|
||||
<div class="gt-ellipsis">
|
||||
{{ locale.show_all_commits }}
|
||||
</div>
|
||||
<div class="gt-ellipsis text light-2 gt-mb-0">
|
||||
{{ locale.stats_num_commits }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- only show the show changes since last review if there is a review AND we are commits ahead of the last review -->
|
||||
<div
|
||||
v-if="lastReviewCommitSha != null" role="menuitem"
|
||||
class="vertical item gt-df gt-fc gt-gap-2 gt-border-secondary-top"
|
||||
:class="{disabled: commitsSinceLastReview === 0}"
|
||||
@keydown.enter="changesSinceLastReviewClick()"
|
||||
@click="changesSinceLastReviewClick()"
|
||||
>
|
||||
<div class="gt-ellipsis">
|
||||
{{ locale.show_changes_since_your_last_review }}
|
||||
</div>
|
||||
<div class="gt-ellipsis text light-2">
|
||||
{{ commitsSinceLastReview }} commits
|
||||
</div>
|
||||
</div>
|
||||
<span v-if="!isLoading" class="info gt-border-secondary-top text light-2">{{ locale.select_commit_hold_shift_for_range }}</span>
|
||||
<template v-for="commit in commits" :key="commit.id">
|
||||
<div
|
||||
class="vertical item gt-df gt-gap-2 gt-border-secondary-top" role="menuitem"
|
||||
:class="{selection: commit.selected, hovered: commit.hovered}"
|
||||
@keydown.enter.exact="commitClicked(commit.id)"
|
||||
@keydown.enter.shift.exact="commitClickedShift(commit)"
|
||||
@mouseover.shift="highlight(commit)"
|
||||
@click.exact="commitClicked(commit.id)"
|
||||
@click.ctrl.exact="commitClicked(commit.id, true)"
|
||||
@click.meta.exact="commitClicked(commit.id, true)"
|
||||
@click.shift.exact.stop.prevent="commitClickedShift(commit)"
|
||||
>
|
||||
<div class="gt-f1 gt-df gt-fc gt-gap-2">
|
||||
<div class="gt-ellipsis commit-list-summary">
|
||||
{{ commit.summary }}
|
||||
</div>
|
||||
<div class="gt-ellipsis text light-2">
|
||||
{{ commit.committer_or_author_name }}
|
||||
<span class="text right">
|
||||
<relative-time class="time-since" prefix="" :datetime="commit.time" data-tooltip-content data-tooltip-interactive="true">{{ commit.time }}</relative-time>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gt-mono">
|
||||
{{ commit.short_sha }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.hovered:not(.selection) {
|
||||
background-color: var(--color-small-accent) !important;
|
||||
|
@ -1,25 +1,3 @@
|
||||
<template>
|
||||
<ol class="diff-detail-box diff-stats gt-m-0" ref="root" v-if="store.fileListIsVisible">
|
||||
<li v-for="file in store.files" :key="file.NameHash">
|
||||
<div class="gt-font-semibold gt-df gt-ac pull-right">
|
||||
<span v-if="file.IsBin" class="gt-ml-1 gt-mr-3">{{ store.binaryFileMessage }}</span>
|
||||
{{ file.IsBin ? '' : file.Addition + file.Deletion }}
|
||||
<span v-if="!file.IsBin" class="diff-stats-bar gt-mx-3" :data-tooltip-content="store.statisticsMessage.replace('%d', (file.Addition + file.Deletion)).replace('%d', file.Addition).replace('%d', file.Deletion)">
|
||||
<div class="diff-stats-add-bar" :style="{ 'width': diffStatsWidth(file.Addition, file.Deletion) }"/>
|
||||
</span>
|
||||
</div>
|
||||
<!-- todo finish all file status, now modify, add, delete and rename -->
|
||||
<span :class="['status', diffTypeToString(file.Type)]" :data-tooltip-content="diffTypeToString(file.Type)"> </span>
|
||||
<a class="file gt-mono" :href="'#diff-' + file.NameHash">{{ file.Name }}</a>
|
||||
</li>
|
||||
<li v-if="store.isIncomplete" class="gt-pt-2">
|
||||
<span class="file gt-df gt-ac gt-sb">{{ store.tooManyFilesMessage }}
|
||||
<a :class="['ui', 'basic', 'tiny', 'button', store.isLoadingNewData ? 'disabled' : '']" @click.stop="loadMoreData">{{ store.showMoreMessage }}</a>
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {loadMoreFiles} from '../features/repo-diff.js';
|
||||
import {diffTreeStore} from '../modules/stores.js';
|
||||
@ -57,3 +35,24 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<ol class="diff-detail-box diff-stats gt-m-0" ref="root" v-if="store.fileListIsVisible">
|
||||
<li v-for="file in store.files" :key="file.NameHash">
|
||||
<div class="gt-font-semibold gt-df gt-ac pull-right">
|
||||
<span v-if="file.IsBin" class="gt-ml-1 gt-mr-3">{{ store.binaryFileMessage }}</span>
|
||||
{{ file.IsBin ? '' : file.Addition + file.Deletion }}
|
||||
<span v-if="!file.IsBin" class="diff-stats-bar gt-mx-3" :data-tooltip-content="store.statisticsMessage.replace('%d', (file.Addition + file.Deletion)).replace('%d', file.Addition).replace('%d', file.Deletion)">
|
||||
<div class="diff-stats-add-bar" :style="{ 'width': diffStatsWidth(file.Addition, file.Deletion) }"/>
|
||||
</span>
|
||||
</div>
|
||||
<!-- todo finish all file status, now modify, add, delete and rename -->
|
||||
<span :class="['status', diffTypeToString(file.Type)]" :data-tooltip-content="diffTypeToString(file.Type)"> </span>
|
||||
<a class="file gt-mono" :href="'#diff-' + file.NameHash">{{ file.Name }}</a>
|
||||
</li>
|
||||
<li v-if="store.isIncomplete" class="gt-pt-2">
|
||||
<span class="file gt-df gt-ac gt-sb">{{ store.tooManyFilesMessage }}
|
||||
<a :class="['ui', 'basic', 'tiny', 'button', store.isLoadingNewData ? 'disabled' : '']" @click.stop="loadMoreData">{{ store.showMoreMessage }}</a>
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</template>
|
||||
|
@ -1,13 +1,3 @@
|
||||
<template>
|
||||
<div v-if="store.fileTreeIsVisible" class="gt-mr-3 gt-mt-3 diff-detail-box">
|
||||
<!-- only render the tree if we're visible. in many cases this is something that doesn't change very often -->
|
||||
<DiffFileTreeItem v-for="item in fileTree" :key="item.name" :item="item"/>
|
||||
<div v-if="store.isIncomplete" class="gt-pt-2">
|
||||
<a :class="['ui', 'basic', 'tiny', 'button', store.isLoadingNewData ? 'disabled' : '']" @click.stop="loadMoreData">{{ store.showMoreMessage }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DiffFileTreeItem from './DiffFileTreeItem.vue';
|
||||
import {loadMoreFiles} from '../features/repo-diff.js';
|
||||
@ -135,3 +125,12 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div v-if="store.fileTreeIsVisible" class="gt-mr-3 gt-mt-3 diff-detail-box">
|
||||
<!-- only render the tree if we're visible. in many cases this is something that doesn't change very often -->
|
||||
<DiffFileTreeItem v-for="item in fileTree" :key="item.name" :item="item"/>
|
||||
<div v-if="store.isIncomplete" class="gt-pt-2">
|
||||
<a :class="['ui', 'basic', 'tiny', 'button', store.isLoadingNewData ? 'disabled' : '']" @click.stop="loadMoreData">{{ store.showMoreMessage }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,27 +1,3 @@
|
||||
<template>
|
||||
<!--title instead of tooltip above as the tooltip needs too much work with the current methods, i.e. not being loaded or staying open for "too long"-->
|
||||
<a
|
||||
v-if="item.isFile" class="item-file"
|
||||
:class="{'selected': store.selectedItem === '#diff-' + item.file.NameHash, 'viewed': item.file.IsViewed}"
|
||||
:title="item.name" :href="'#diff-' + item.file.NameHash"
|
||||
>
|
||||
<!-- file -->
|
||||
<SvgIcon name="octicon-file"/>
|
||||
<span class="gt-ellipsis gt-f1">{{ item.name }}</span>
|
||||
<SvgIcon :name="getIconForDiffType(item.file.Type).name" :class="getIconForDiffType(item.file.Type).classes"/>
|
||||
</a>
|
||||
<div v-else class="item-directory" :title="item.name" @click.stop="collapsed = !collapsed">
|
||||
<!-- directory -->
|
||||
<SvgIcon :name="collapsed ? 'octicon-chevron-right' : 'octicon-chevron-down'"/>
|
||||
<SvgIcon class="text primary" name="octicon-file-directory-fill"/>
|
||||
<span class="gt-ellipsis">{{ item.name }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="item.children?.length" v-show="!collapsed" class="sub-items">
|
||||
<DiffFileTreeItem v-for="childItem in item.children" :key="childItem.name" :item="childItem"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {SvgIcon} from '../svg.js';
|
||||
import {diffTreeStore} from '../modules/stores.js';
|
||||
@ -52,7 +28,29 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<!--title instead of tooltip above as the tooltip needs too much work with the current methods, i.e. not being loaded or staying open for "too long"-->
|
||||
<a
|
||||
v-if="item.isFile" class="item-file"
|
||||
:class="{'selected': store.selectedItem === '#diff-' + item.file.NameHash, 'viewed': item.file.IsViewed}"
|
||||
:title="item.name" :href="'#diff-' + item.file.NameHash"
|
||||
>
|
||||
<!-- file -->
|
||||
<SvgIcon name="octicon-file"/>
|
||||
<span class="gt-ellipsis gt-f1">{{ item.name }}</span>
|
||||
<SvgIcon :name="getIconForDiffType(item.file.Type).name" :class="getIconForDiffType(item.file.Type).classes"/>
|
||||
</a>
|
||||
<div v-else class="item-directory" :title="item.name" @click.stop="collapsed = !collapsed">
|
||||
<!-- directory -->
|
||||
<SvgIcon :name="collapsed ? 'octicon-chevron-right' : 'octicon-chevron-down'"/>
|
||||
<SvgIcon class="text primary" name="octicon-file-directory-fill"/>
|
||||
<span class="gt-ellipsis">{{ item.name }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="item.children?.length" v-show="!collapsed" class="sub-items">
|
||||
<DiffFileTreeItem v-for="childItem in item.children" :key="childItem.name" :item="childItem"/>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
a, a:hover {
|
||||
text-decoration: none;
|
||||
|
@ -1,3 +1,80 @@
|
||||
<script>
|
||||
import {SvgIcon} from '../svg.js';
|
||||
|
||||
const {csrfToken, pageData} = window.config;
|
||||
|
||||
export default {
|
||||
components: {SvgIcon},
|
||||
data: () => ({
|
||||
csrfToken,
|
||||
mergeForm: pageData.pullRequestMergeForm,
|
||||
|
||||
mergeTitleFieldValue: '',
|
||||
mergeMessageFieldValue: '',
|
||||
deleteBranchAfterMerge: false,
|
||||
autoMergeWhenSucceed: false,
|
||||
|
||||
mergeStyle: '',
|
||||
mergeStyleDetail: { // dummy only, these values will come from one of the mergeForm.mergeStyles
|
||||
hideMergeMessageTexts: false,
|
||||
textDoMerge: '',
|
||||
mergeTitleFieldText: '',
|
||||
mergeMessageFieldText: '',
|
||||
hideAutoMerge: false,
|
||||
},
|
||||
mergeStyleAllowedCount: 0,
|
||||
|
||||
showMergeStyleMenu: false,
|
||||
showActionForm: false,
|
||||
}),
|
||||
computed: {
|
||||
mergeButtonStyleClass() {
|
||||
if (this.mergeForm.allOverridableChecksOk) return 'green';
|
||||
return this.autoMergeWhenSucceed ? 'blue' : 'red';
|
||||
},
|
||||
forceMerge() {
|
||||
return this.mergeForm.canMergeNow && !this.mergeForm.allOverridableChecksOk;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
mergeStyle(val) {
|
||||
this.mergeStyleDetail = this.mergeForm.mergeStyles.find((e) => e.name === val);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.mergeStyleAllowedCount = this.mergeForm.mergeStyles.reduce((v, msd) => v + (msd.allowed ? 1 : 0), 0);
|
||||
|
||||
let mergeStyle = this.mergeForm.mergeStyles.find((e) => e.allowed && e.name === this.mergeForm.defaultMergeStyle)?.name;
|
||||
if (!mergeStyle) mergeStyle = this.mergeForm.mergeStyles.find((e) => e.allowed)?.name;
|
||||
this.switchMergeStyle(mergeStyle, !this.mergeForm.canMergeNow);
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('mouseup', this.hideMergeStyleMenu);
|
||||
},
|
||||
unmounted() {
|
||||
document.removeEventListener('mouseup', this.hideMergeStyleMenu);
|
||||
},
|
||||
methods: {
|
||||
hideMergeStyleMenu() {
|
||||
this.showMergeStyleMenu = false;
|
||||
},
|
||||
toggleActionForm(show) {
|
||||
this.showActionForm = show;
|
||||
if (!show) return;
|
||||
this.deleteBranchAfterMerge = this.mergeForm.defaultDeleteBranchAfterMerge;
|
||||
this.mergeTitleFieldValue = this.mergeStyleDetail.mergeTitleFieldText;
|
||||
this.mergeMessageFieldValue = this.mergeStyleDetail.mergeMessageFieldText;
|
||||
},
|
||||
switchMergeStyle(name, autoMerge = false) {
|
||||
this.mergeStyle = name;
|
||||
this.autoMergeWhenSucceed = autoMerge;
|
||||
},
|
||||
clearMergeMessage() {
|
||||
this.mergeMessageFieldValue = this.mergeForm.defaultMergeMessage;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<!--
|
||||
if this component is shown, either the user is an admin (can do a merge without checks), or they are a writer who has the permission to do a merge
|
||||
@ -106,85 +183,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {SvgIcon} from '../svg.js';
|
||||
|
||||
const {csrfToken, pageData} = window.config;
|
||||
|
||||
export default {
|
||||
components: {SvgIcon},
|
||||
data: () => ({
|
||||
csrfToken,
|
||||
mergeForm: pageData.pullRequestMergeForm,
|
||||
|
||||
mergeTitleFieldValue: '',
|
||||
mergeMessageFieldValue: '',
|
||||
deleteBranchAfterMerge: false,
|
||||
autoMergeWhenSucceed: false,
|
||||
|
||||
mergeStyle: '',
|
||||
mergeStyleDetail: { // dummy only, these values will come from one of the mergeForm.mergeStyles
|
||||
hideMergeMessageTexts: false,
|
||||
textDoMerge: '',
|
||||
mergeTitleFieldText: '',
|
||||
mergeMessageFieldText: '',
|
||||
hideAutoMerge: false,
|
||||
},
|
||||
mergeStyleAllowedCount: 0,
|
||||
|
||||
showMergeStyleMenu: false,
|
||||
showActionForm: false,
|
||||
}),
|
||||
computed: {
|
||||
mergeButtonStyleClass() {
|
||||
if (this.mergeForm.allOverridableChecksOk) return 'green';
|
||||
return this.autoMergeWhenSucceed ? 'blue' : 'red';
|
||||
},
|
||||
forceMerge() {
|
||||
return this.mergeForm.canMergeNow && !this.mergeForm.allOverridableChecksOk;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
mergeStyle(val) {
|
||||
this.mergeStyleDetail = this.mergeForm.mergeStyles.find((e) => e.name === val);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.mergeStyleAllowedCount = this.mergeForm.mergeStyles.reduce((v, msd) => v + (msd.allowed ? 1 : 0), 0);
|
||||
|
||||
let mergeStyle = this.mergeForm.mergeStyles.find((e) => e.allowed && e.name === this.mergeForm.defaultMergeStyle)?.name;
|
||||
if (!mergeStyle) mergeStyle = this.mergeForm.mergeStyles.find((e) => e.allowed)?.name;
|
||||
this.switchMergeStyle(mergeStyle, !this.mergeForm.canMergeNow);
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('mouseup', this.hideMergeStyleMenu);
|
||||
},
|
||||
unmounted() {
|
||||
document.removeEventListener('mouseup', this.hideMergeStyleMenu);
|
||||
},
|
||||
methods: {
|
||||
hideMergeStyleMenu() {
|
||||
this.showMergeStyleMenu = false;
|
||||
},
|
||||
toggleActionForm(show) {
|
||||
this.showActionForm = show;
|
||||
if (!show) return;
|
||||
this.deleteBranchAfterMerge = this.mergeForm.defaultDeleteBranchAfterMerge;
|
||||
this.mergeTitleFieldValue = this.mergeStyleDetail.mergeTitleFieldText;
|
||||
this.mergeMessageFieldValue = this.mergeStyleDetail.mergeMessageFieldText;
|
||||
},
|
||||
switchMergeStyle(name, autoMerge = false) {
|
||||
this.mergeStyle = name;
|
||||
this.autoMergeWhenSucceed = autoMerge;
|
||||
},
|
||||
clearMergeMessage() {
|
||||
this.mergeMessageFieldValue = this.mergeForm.defaultMergeMessage;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* to keep UI the same, at the moment we are still using some Fomantic UI styles, but we do not use their scripts, so we need to fine tune some styles */
|
||||
.ui.dropdown .menu.show {
|
||||
|
@ -1,124 +1,3 @@
|
||||
<template>
|
||||
<div class="ui container action-view-container">
|
||||
<div class="action-view-header">
|
||||
<div class="action-info-summary">
|
||||
<div class="action-info-summary-title">
|
||||
<ActionRunStatus :locale-status="locale.status[run.status]" :status="run.status" :size="20"/>
|
||||
<h2 class="action-info-summary-title-text">
|
||||
{{ run.title }}
|
||||
</h2>
|
||||
</div>
|
||||
<button class="ui basic small compact button primary" @click="approveRun()" v-if="run.canApprove">
|
||||
{{ locale.approve }}
|
||||
</button>
|
||||
<button class="ui basic small compact button red" @click="cancelRun()" v-else-if="run.canCancel">
|
||||
{{ locale.cancel }}
|
||||
</button>
|
||||
<button class="ui basic small compact button gt-mr-0 link-action" :data-url="`${run.link}/rerun`" v-else-if="run.canRerun">
|
||||
{{ locale.rerun_all }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="action-commit-summary">
|
||||
{{ run.commit.localeCommit }}
|
||||
<a class="muted" :href="run.commit.link">{{ run.commit.shortSHA }}</a>
|
||||
{{ run.commit.localePushedBy }}
|
||||
<a class="muted" :href="run.commit.pusher.link">{{ run.commit.pusher.displayName }}</a>
|
||||
<span class="ui label" v-if="run.commit.shortSHA">
|
||||
<a :href="run.commit.branch.link">{{ run.commit.branch.name }}</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-view-body">
|
||||
<div class="action-view-left">
|
||||
<div class="job-group-section">
|
||||
<div class="job-brief-list">
|
||||
<a class="job-brief-item" :href="run.link+'/jobs/'+index" :class="parseInt(jobIndex) === index ? 'selected' : ''" v-for="(job, index) in run.jobs" :key="job.id" @mouseenter="onHoverRerunIndex = job.id" @mouseleave="onHoverRerunIndex = -1">
|
||||
<div class="job-brief-item-left">
|
||||
<ActionRunStatus :locale-status="locale.status[job.status]" :status="job.status"/>
|
||||
<span class="job-brief-name gt-mx-3 gt-ellipsis">{{ job.name }}</span>
|
||||
</div>
|
||||
<span class="job-brief-item-right">
|
||||
<SvgIcon name="octicon-sync" role="button" :data-tooltip-content="locale.rerun" class="job-brief-rerun gt-mx-3 link-action" :data-url="`${run.link}/jobs/${index}/rerun`" v-if="job.canRerun && onHoverRerunIndex === job.id"/>
|
||||
<span class="step-summary-duration">{{ job.duration }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="job-artifacts" v-if="artifacts.length > 0">
|
||||
<div class="job-artifacts-title">
|
||||
{{ locale.artifactsTitle }}
|
||||
</div>
|
||||
<ul class="job-artifacts-list">
|
||||
<li class="job-artifacts-item" v-for="artifact in artifacts" :key="artifact.name">
|
||||
<a class="job-artifacts-link" target="_blank" :href="run.link+'/artifacts/'+artifact.name">
|
||||
<SvgIcon name="octicon-file" class="ui text black job-artifacts-icon"/>{{ artifact.name }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-view-right">
|
||||
<div class="job-info-header">
|
||||
<div class="job-info-header-left">
|
||||
<h3 class="job-info-header-title">
|
||||
{{ currentJob.title }}
|
||||
</h3>
|
||||
<p class="job-info-header-detail">
|
||||
{{ currentJob.detail }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="job-info-header-right">
|
||||
<div class="ui top right pointing dropdown custom jump item" @click.stop="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
|
||||
<button class="btn gt-interact-bg gt-p-3">
|
||||
<SvgIcon name="octicon-gear" :size="18"/>
|
||||
</button>
|
||||
<div class="menu transition action-job-menu" :class="{visible: menuVisible}" v-if="menuVisible" v-cloak>
|
||||
<a class="item" @click="toggleTimeDisplay('seconds')">
|
||||
<i class="icon"><SvgIcon :name="timeVisible['log-time-seconds'] ? 'octicon-check' : 'gitea-empty-checkbox'"/></i>
|
||||
{{ locale.showLogSeconds }}
|
||||
</a>
|
||||
<a class="item" @click="toggleTimeDisplay('stamp')">
|
||||
<i class="icon"><SvgIcon :name="timeVisible['log-time-stamp'] ? 'octicon-check' : 'gitea-empty-checkbox'"/></i>
|
||||
{{ locale.showTimeStamps }}
|
||||
</a>
|
||||
<a class="item" @click="toggleFullScreen()">
|
||||
<i class="icon"><SvgIcon :name="isFullScreen ? 'octicon-check' : 'gitea-empty-checkbox'"/></i>
|
||||
{{ locale.showFullScreen }}
|
||||
</a>
|
||||
<div class="divider"/>
|
||||
<a :class="['item', currentJob.steps.length === 0 ? 'disabled' : '']" :href="run.link+'/jobs/'+jobIndex+'/logs'" target="_blank">
|
||||
<i class="icon"><SvgIcon name="octicon-download"/></i>
|
||||
{{ locale.downloadLogs }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="job-step-container" ref="steps">
|
||||
<div class="job-step-section" v-for="(jobStep, i) in currentJob.steps" :key="i">
|
||||
<div class="job-step-summary" @click.stop="toggleStepLogs(i)" :class="currentJobStepsStates[i].expanded ? 'selected' : ''">
|
||||
<!-- If the job is done and the job step log is loaded for the first time, show the loading icon
|
||||
currentJobStepsStates[i].cursor === null means the log is loaded for the first time
|
||||
-->
|
||||
<SvgIcon v-if="isDone(run.status) && currentJobStepsStates[i].expanded && currentJobStepsStates[i].cursor === null" name="octicon-sync" class="gt-mr-3 job-status-rotate"/>
|
||||
<SvgIcon v-else :name="currentJobStepsStates[i].expanded ? 'octicon-chevron-down': 'octicon-chevron-right'" class="gt-mr-3"/>
|
||||
<ActionRunStatus :status="jobStep.status" class="gt-mr-3"/>
|
||||
|
||||
<span class="step-summary-msg gt-ellipsis">{{ jobStep.summary }}</span>
|
||||
<span class="step-summary-duration">{{ jobStep.duration }}</span>
|
||||
</div>
|
||||
|
||||
<!-- the log elements could be a lot, do not use v-if to destroy/reconstruct the DOM,
|
||||
use native DOM elements for "log line" to improve performance, Vue is not suitable for managing so many reactive elements. -->
|
||||
<div class="job-step-logs" ref="logs" v-show="currentJobStepsStates[i].expanded"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {SvgIcon} from '../svg.js';
|
||||
import ActionRunStatus from './ActionRunStatus.vue';
|
||||
@ -472,9 +351,127 @@ export function initRepositoryActionView() {
|
||||
});
|
||||
view.mount(el);
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="ui container action-view-container">
|
||||
<div class="action-view-header">
|
||||
<div class="action-info-summary">
|
||||
<div class="action-info-summary-title">
|
||||
<ActionRunStatus :locale-status="locale.status[run.status]" :status="run.status" :size="20"/>
|
||||
<h2 class="action-info-summary-title-text">
|
||||
{{ run.title }}
|
||||
</h2>
|
||||
</div>
|
||||
<button class="ui basic small compact button primary" @click="approveRun()" v-if="run.canApprove">
|
||||
{{ locale.approve }}
|
||||
</button>
|
||||
<button class="ui basic small compact button red" @click="cancelRun()" v-else-if="run.canCancel">
|
||||
{{ locale.cancel }}
|
||||
</button>
|
||||
<button class="ui basic small compact button gt-mr-0 link-action" :data-url="`${run.link}/rerun`" v-else-if="run.canRerun">
|
||||
{{ locale.rerun_all }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="action-commit-summary">
|
||||
{{ run.commit.localeCommit }}
|
||||
<a class="muted" :href="run.commit.link">{{ run.commit.shortSHA }}</a>
|
||||
{{ run.commit.localePushedBy }}
|
||||
<a class="muted" :href="run.commit.pusher.link">{{ run.commit.pusher.displayName }}</a>
|
||||
<span class="ui label" v-if="run.commit.shortSHA">
|
||||
<a :href="run.commit.branch.link">{{ run.commit.branch.name }}</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-view-body">
|
||||
<div class="action-view-left">
|
||||
<div class="job-group-section">
|
||||
<div class="job-brief-list">
|
||||
<a class="job-brief-item" :href="run.link+'/jobs/'+index" :class="parseInt(jobIndex) === index ? 'selected' : ''" v-for="(job, index) in run.jobs" :key="job.id" @mouseenter="onHoverRerunIndex = job.id" @mouseleave="onHoverRerunIndex = -1">
|
||||
<div class="job-brief-item-left">
|
||||
<ActionRunStatus :locale-status="locale.status[job.status]" :status="job.status"/>
|
||||
<span class="job-brief-name gt-mx-3 gt-ellipsis">{{ job.name }}</span>
|
||||
</div>
|
||||
<span class="job-brief-item-right">
|
||||
<SvgIcon name="octicon-sync" role="button" :data-tooltip-content="locale.rerun" class="job-brief-rerun gt-mx-3 link-action" :data-url="`${run.link}/jobs/${index}/rerun`" v-if="job.canRerun && onHoverRerunIndex === job.id"/>
|
||||
<span class="step-summary-duration">{{ job.duration }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="job-artifacts" v-if="artifacts.length > 0">
|
||||
<div class="job-artifacts-title">
|
||||
{{ locale.artifactsTitle }}
|
||||
</div>
|
||||
<ul class="job-artifacts-list">
|
||||
<li class="job-artifacts-item" v-for="artifact in artifacts" :key="artifact.name">
|
||||
<a class="job-artifacts-link" target="_blank" :href="run.link+'/artifacts/'+artifact.name">
|
||||
<SvgIcon name="octicon-file" class="ui text black job-artifacts-icon"/>{{ artifact.name }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-view-right">
|
||||
<div class="job-info-header">
|
||||
<div class="job-info-header-left">
|
||||
<h3 class="job-info-header-title">
|
||||
{{ currentJob.title }}
|
||||
</h3>
|
||||
<p class="job-info-header-detail">
|
||||
{{ currentJob.detail }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="job-info-header-right">
|
||||
<div class="ui top right pointing dropdown custom jump item" @click.stop="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
|
||||
<button class="btn gt-interact-bg gt-p-3">
|
||||
<SvgIcon name="octicon-gear" :size="18"/>
|
||||
</button>
|
||||
<div class="menu transition action-job-menu" :class="{visible: menuVisible}" v-if="menuVisible" v-cloak>
|
||||
<a class="item" @click="toggleTimeDisplay('seconds')">
|
||||
<i class="icon"><SvgIcon :name="timeVisible['log-time-seconds'] ? 'octicon-check' : 'gitea-empty-checkbox'"/></i>
|
||||
{{ locale.showLogSeconds }}
|
||||
</a>
|
||||
<a class="item" @click="toggleTimeDisplay('stamp')">
|
||||
<i class="icon"><SvgIcon :name="timeVisible['log-time-stamp'] ? 'octicon-check' : 'gitea-empty-checkbox'"/></i>
|
||||
{{ locale.showTimeStamps }}
|
||||
</a>
|
||||
<a class="item" @click="toggleFullScreen()">
|
||||
<i class="icon"><SvgIcon :name="isFullScreen ? 'octicon-check' : 'gitea-empty-checkbox'"/></i>
|
||||
{{ locale.showFullScreen }}
|
||||
</a>
|
||||
<div class="divider"/>
|
||||
<a :class="['item', currentJob.steps.length === 0 ? 'disabled' : '']" :href="run.link+'/jobs/'+jobIndex+'/logs'" target="_blank">
|
||||
<i class="icon"><SvgIcon name="octicon-download"/></i>
|
||||
{{ locale.downloadLogs }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="job-step-container" ref="steps">
|
||||
<div class="job-step-section" v-for="(jobStep, i) in currentJob.steps" :key="i">
|
||||
<div class="job-step-summary" @click.stop="toggleStepLogs(i)" :class="currentJobStepsStates[i].expanded ? 'selected' : ''">
|
||||
<!-- If the job is done and the job step log is loaded for the first time, show the loading icon
|
||||
currentJobStepsStates[i].cursor === null means the log is loaded for the first time
|
||||
-->
|
||||
<SvgIcon v-if="isDone(run.status) && currentJobStepsStates[i].expanded && currentJobStepsStates[i].cursor === null" name="octicon-sync" class="gt-mr-3 job-status-rotate"/>
|
||||
<SvgIcon v-else :name="currentJobStepsStates[i].expanded ? 'octicon-chevron-down': 'octicon-chevron-right'" class="gt-mr-3"/>
|
||||
<ActionRunStatus :status="jobStep.status" class="gt-mr-3"/>
|
||||
|
||||
<span class="step-summary-msg gt-ellipsis">{{ jobStep.summary }}</span>
|
||||
<span class="step-summary-duration">{{ jobStep.duration }}</span>
|
||||
</div>
|
||||
|
||||
<!-- the log elements could be a lot, do not use v-if to destroy/reconstruct the DOM,
|
||||
use native DOM elements for "log line" to improve performance, Vue is not suitable for managing so many reactive elements. -->
|
||||
<div class="job-step-logs" ref="logs" v-show="currentJobStepsStates[i].expanded"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.action-view-body {
|
||||
padding-top: 12px;
|
||||
|
@ -1,54 +1,3 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="activity-bar-graph" ref="style" style="width: 0; height: 0;"/>
|
||||
<div class="activity-bar-graph-alt" ref="altStyle" style="width: 0; height: 0;"/>
|
||||
<vue-bar-graph
|
||||
:points="graphPoints"
|
||||
:show-x-axis="true"
|
||||
:show-y-axis="false"
|
||||
:show-values="true"
|
||||
:width="graphWidth"
|
||||
:bar-color="colors.barColor"
|
||||
:text-color="colors.textColor"
|
||||
:text-alt-color="colors.textAltColor"
|
||||
:height="100"
|
||||
:label-height="20"
|
||||
>
|
||||
<template #label="opt">
|
||||
<g v-for="(author, idx) in graphAuthors" :key="author.position">
|
||||
<a
|
||||
v-if="opt.bar.index === idx && author.home_link"
|
||||
:href="author.home_link"
|
||||
>
|
||||
<image
|
||||
:x="`${opt.bar.midPoint - 10}px`"
|
||||
:y="`${opt.bar.yLabel}px`"
|
||||
height="20"
|
||||
width="20"
|
||||
:href="author.avatar_link"
|
||||
/>
|
||||
</a>
|
||||
<image
|
||||
v-else-if="opt.bar.index === idx"
|
||||
:x="`${opt.bar.midPoint - 10}px`"
|
||||
:y="`${opt.bar.yLabel}px`"
|
||||
height="20"
|
||||
width="20"
|
||||
:href="author.avatar_link"
|
||||
/>
|
||||
</g>
|
||||
</template>
|
||||
<template #title="opt">
|
||||
<tspan v-for="(author, idx) in graphAuthors" :key="author.position">
|
||||
<tspan v-if="opt.bar.index === idx">
|
||||
{{ author.name }}
|
||||
</tspan>
|
||||
</tspan>
|
||||
</template>
|
||||
</vue-bar-graph>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueBarGraph from 'vue-bar-graph';
|
||||
import {createApp} from 'vue';
|
||||
@ -110,3 +59,53 @@ export function initRepoActivityTopAuthorsChart() {
|
||||
|
||||
export default sfc; // activate the IDE's Vue plugin
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="activity-bar-graph" ref="style" style="width: 0; height: 0;"/>
|
||||
<div class="activity-bar-graph-alt" ref="altStyle" style="width: 0; height: 0;"/>
|
||||
<vue-bar-graph
|
||||
:points="graphPoints"
|
||||
:show-x-axis="true"
|
||||
:show-y-axis="false"
|
||||
:show-values="true"
|
||||
:width="graphWidth"
|
||||
:bar-color="colors.barColor"
|
||||
:text-color="colors.textColor"
|
||||
:text-alt-color="colors.textAltColor"
|
||||
:height="100"
|
||||
:label-height="20"
|
||||
>
|
||||
<template #label="opt">
|
||||
<g v-for="(author, idx) in graphAuthors" :key="author.position">
|
||||
<a
|
||||
v-if="opt.bar.index === idx && author.home_link"
|
||||
:href="author.home_link"
|
||||
>
|
||||
<image
|
||||
:x="`${opt.bar.midPoint - 10}px`"
|
||||
:y="`${opt.bar.yLabel}px`"
|
||||
height="20"
|
||||
width="20"
|
||||
:href="author.avatar_link"
|
||||
/>
|
||||
</a>
|
||||
<image
|
||||
v-else-if="opt.bar.index === idx"
|
||||
:x="`${opt.bar.midPoint - 10}px`"
|
||||
:y="`${opt.bar.yLabel}px`"
|
||||
height="20"
|
||||
width="20"
|
||||
:href="author.avatar_link"
|
||||
/>
|
||||
</g>
|
||||
</template>
|
||||
<template #title="opt">
|
||||
<tspan v-for="(author, idx) in graphAuthors" :key="author.position">
|
||||
<tspan v-if="opt.bar.index === idx">
|
||||
{{ author.name }}
|
||||
</tspan>
|
||||
</tspan>
|
||||
</template>
|
||||
</vue-bar-graph>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,76 +1,3 @@
|
||||
<template>
|
||||
<div class="ui dropdown custom">
|
||||
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button gt-df gt-m-0" @click="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
|
||||
<span class="text gt-df gt-ac gt-mr-2">
|
||||
<template v-if="release">{{ textReleaseCompare }}</template>
|
||||
<template v-else>
|
||||
<svg-icon v-if="isViewTag" name="octicon-tag"/>
|
||||
<svg-icon v-else name="octicon-git-branch"/>
|
||||
<strong ref="dropdownRefName" class="gt-ml-3">{{ refNameText }}</strong>
|
||||
</template>
|
||||
</span>
|
||||
<svg-icon name="octicon-triangle-down" :size="14" class-name="dropdown icon"/>
|
||||
</button>
|
||||
<div class="menu transition" :class="{visible: menuVisible}" v-show="menuVisible" v-cloak>
|
||||
<div class="ui icon search input">
|
||||
<i class="icon"><svg-icon name="octicon-filter" :size="16"/></i>
|
||||
<input name="search" ref="searchField" autocomplete="off" v-model="searchTerm" @keydown="keydown($event)" :placeholder="searchFieldPlaceholder">
|
||||
</div>
|
||||
<div v-if="showBranchesInDropdown" class="branch-tag-tab">
|
||||
<a class="branch-tag-item muted" :class="{active: mode === 'branches'}" href="#" @click="handleTabSwitch('branches')">
|
||||
<svg-icon name="octicon-git-branch" :size="16" class-name="gt-mr-2"/>{{ textBranches }}
|
||||
</a>
|
||||
<a v-if="!noTag" class="branch-tag-item muted" :class="{active: mode === 'tags'}" href="#" @click="handleTabSwitch('tags')">
|
||||
<svg-icon name="octicon-tag" :size="16" class-name="gt-mr-2"/>{{ textTags }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="branch-tag-divider"/>
|
||||
<div class="scrolling menu" ref="scrollContainer">
|
||||
<svg-icon name="octicon-rss" symbol-id="svg-symbol-octicon-rss"/>
|
||||
<div class="loading-indicator is-loading" v-if="isLoading"/>
|
||||
<div v-for="(item, index) in filteredItems" :key="item.name" class="item" :class="{selected: item.selected, active: active === index}" @click="selectItem(item)" :ref="'listItem' + index">
|
||||
{{ item.name }}
|
||||
<div class="ui label" v-if="item.name===defaultBranch && mode === 'branches'">
|
||||
{{ textDefaultBranchLabel }}
|
||||
</div>
|
||||
<a v-show="enableFeed && mode === 'branches'" role="button" class="rss-icon gt-float-right" :href="rssURLPrefix + item.url" target="_blank" @click.stop>
|
||||
<!-- creating a lot of Vue component is pretty slow, so we use a static SVG here -->
|
||||
<svg width="14" height="14" class="svg octicon-rss"><use href="#svg-symbol-octicon-rss"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div class="item" v-if="showCreateNewBranch" :class="{active: active === filteredItems.length}" :ref="'listItem' + filteredItems.length">
|
||||
<a href="#" @click="createNewBranch()">
|
||||
<div v-show="shouldCreateTag">
|
||||
<i class="reference tags icon"/>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-html="textCreateTag.replace('%s', searchTerm)"/>
|
||||
</div>
|
||||
<div v-show="!shouldCreateTag">
|
||||
<svg-icon name="octicon-git-branch"/>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-html="textCreateBranch.replace('%s', searchTerm)"/>
|
||||
</div>
|
||||
<div class="text small">
|
||||
<span v-if="isViewBranch || release">{{ textCreateBranchFrom.replace('%s', branchName) }}</span>
|
||||
<span v-else-if="isViewTag">{{ textCreateBranchFrom.replace('%s', tagName) }}</span>
|
||||
<span v-else>{{ textCreateBranchFrom.replace('%s', commitIdShort) }}</span>
|
||||
</div>
|
||||
</a>
|
||||
<form ref="newBranchForm" :action="formActionUrl" method="post">
|
||||
<input type="hidden" name="_csrf" :value="csrfToken">
|
||||
<input type="hidden" name="new_branch_name" v-model="searchTerm">
|
||||
<input type="hidden" name="create_tag" v-model="shouldCreateTag">
|
||||
<input type="hidden" name="current_path" v-model="treePath" v-if="treePath">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="message" v-if="showNoResults && !isLoading">
|
||||
{{ noResults }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApp, nextTick} from 'vue';
|
||||
import $ from 'jquery';
|
||||
@ -317,7 +244,78 @@ export function initRepoBranchTagSelector(selector) {
|
||||
|
||||
export default sfc; // activate IDE's Vue plugin
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="ui dropdown custom">
|
||||
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button gt-df gt-m-0" @click="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
|
||||
<span class="text gt-df gt-ac gt-mr-2">
|
||||
<template v-if="release">{{ textReleaseCompare }}</template>
|
||||
<template v-else>
|
||||
<svg-icon v-if="isViewTag" name="octicon-tag"/>
|
||||
<svg-icon v-else name="octicon-git-branch"/>
|
||||
<strong ref="dropdownRefName" class="gt-ml-3">{{ refNameText }}</strong>
|
||||
</template>
|
||||
</span>
|
||||
<svg-icon name="octicon-triangle-down" :size="14" class-name="dropdown icon"/>
|
||||
</button>
|
||||
<div class="menu transition" :class="{visible: menuVisible}" v-show="menuVisible" v-cloak>
|
||||
<div class="ui icon search input">
|
||||
<i class="icon"><svg-icon name="octicon-filter" :size="16"/></i>
|
||||
<input name="search" ref="searchField" autocomplete="off" v-model="searchTerm" @keydown="keydown($event)" :placeholder="searchFieldPlaceholder">
|
||||
</div>
|
||||
<div v-if="showBranchesInDropdown" class="branch-tag-tab">
|
||||
<a class="branch-tag-item muted" :class="{active: mode === 'branches'}" href="#" @click="handleTabSwitch('branches')">
|
||||
<svg-icon name="octicon-git-branch" :size="16" class-name="gt-mr-2"/>{{ textBranches }}
|
||||
</a>
|
||||
<a v-if="!noTag" class="branch-tag-item muted" :class="{active: mode === 'tags'}" href="#" @click="handleTabSwitch('tags')">
|
||||
<svg-icon name="octicon-tag" :size="16" class-name="gt-mr-2"/>{{ textTags }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="branch-tag-divider"/>
|
||||
<div class="scrolling menu" ref="scrollContainer">
|
||||
<svg-icon name="octicon-rss" symbol-id="svg-symbol-octicon-rss"/>
|
||||
<div class="loading-indicator is-loading" v-if="isLoading"/>
|
||||
<div v-for="(item, index) in filteredItems" :key="item.name" class="item" :class="{selected: item.selected, active: active === index}" @click="selectItem(item)" :ref="'listItem' + index">
|
||||
{{ item.name }}
|
||||
<div class="ui label" v-if="item.name===defaultBranch && mode === 'branches'">
|
||||
{{ textDefaultBranchLabel }}
|
||||
</div>
|
||||
<a v-show="enableFeed && mode === 'branches'" role="button" class="rss-icon gt-float-right" :href="rssURLPrefix + item.url" target="_blank" @click.stop>
|
||||
<!-- creating a lot of Vue component is pretty slow, so we use a static SVG here -->
|
||||
<svg width="14" height="14" class="svg octicon-rss"><use href="#svg-symbol-octicon-rss"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div class="item" v-if="showCreateNewBranch" :class="{active: active === filteredItems.length}" :ref="'listItem' + filteredItems.length">
|
||||
<a href="#" @click="createNewBranch()">
|
||||
<div v-show="shouldCreateTag">
|
||||
<i class="reference tags icon"/>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-html="textCreateTag.replace('%s', searchTerm)"/>
|
||||
</div>
|
||||
<div v-show="!shouldCreateTag">
|
||||
<svg-icon name="octicon-git-branch"/>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-html="textCreateBranch.replace('%s', searchTerm)"/>
|
||||
</div>
|
||||
<div class="text small">
|
||||
<span v-if="isViewBranch || release">{{ textCreateBranchFrom.replace('%s', branchName) }}</span>
|
||||
<span v-else-if="isViewTag">{{ textCreateBranchFrom.replace('%s', tagName) }}</span>
|
||||
<span v-else>{{ textCreateBranchFrom.replace('%s', commitIdShort) }}</span>
|
||||
</div>
|
||||
</a>
|
||||
<form ref="newBranchForm" :action="formActionUrl" method="post">
|
||||
<input type="hidden" name="_csrf" :value="csrfToken">
|
||||
<input type="hidden" name="new_branch_name" v-model="searchTerm">
|
||||
<input type="hidden" name="create_tag" v-model="shouldCreateTag">
|
||||
<input type="hidden" name="current_path" v-model="treePath" v-if="treePath">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="message" v-if="showNoResults && !isLoading">
|
||||
{{ noResults }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.branch-tag-tab {
|
||||
padding: 0 10px;
|
||||
|
@ -1,28 +1,3 @@
|
||||
<template>
|
||||
<div v-for="category in categories" :key="category" class="field gt-pl-2 gt-pb-2 access-token-category">
|
||||
<label class="category-label" :for="'access-token-scope-' + category">
|
||||
{{ category }}
|
||||
</label>
|
||||
<div class="gitea-select">
|
||||
<select
|
||||
class="ui selection access-token-select"
|
||||
name="scope"
|
||||
:id="'access-token-scope-' + category"
|
||||
>
|
||||
<option value="">
|
||||
{{ noAccessLabel }}
|
||||
</option>
|
||||
<option :value="'read:' + category">
|
||||
{{ readLabel }}
|
||||
</option>
|
||||
<option :value="'write:' + category">
|
||||
{{ writeLabel }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createApp} from 'vue';
|
||||
import {hideElem, showElem} from '../utils/dom.js';
|
||||
@ -111,3 +86,27 @@ export function initScopedAccessTokenCategories() {
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div v-for="category in categories" :key="category" class="field gt-pl-2 gt-pb-2 access-token-category">
|
||||
<label class="category-label" :for="'access-token-scope-' + category">
|
||||
{{ category }}
|
||||
</label>
|
||||
<div class="gitea-select">
|
||||
<select
|
||||
class="ui selection access-token-select"
|
||||
name="scope"
|
||||
:id="'access-token-scope-' + category"
|
||||
>
|
||||
<option value="">
|
||||
{{ noAccessLabel }}
|
||||
</option>
|
||||
<option :value="'read:' + category">
|
||||
{{ readLabel }}
|
||||
</option>
|
||||
<option :value="'write:' + category">
|
||||
{{ writeLabel }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
Loading…
x
Reference in New Issue
Block a user