aboutsummaryrefslogtreecommitdiffstats
path: root/web_src/js
diff options
context:
space:
mode:
authorsilverwind <me@silverwind.io>2023-09-02 16:59:07 +0200
committerGitHub <noreply@github.com>2023-09-02 14:59:07 +0000
commit9a3de436f452144933888fb1e4f336efeb93293a (patch)
treee49c4037604de030a8552a5deca180c240c28484 /web_src/js
parent79f73299710fe8596b6ea31c0fa0ab97ab3dc801 (diff)
downloadgitea-9a3de436f452144933888fb1e4f336efeb93293a.tar.gz
gitea-9a3de436f452144933888fb1e4f336efeb93293a.zip
Reorder blocks in vue SFCs (#26874)
The [recommended order](https://vuejs.org/guide/scaling-up/sfc.html) for SFC blocks is script -> template -> style, which we were violating because template and script were swapped. I do find script first also easier to read because the imports are on top, letting me immideatly see a component's dependencies. This is a pure cut-paste refactor with some removal of some empty lines. --------- Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'web_src/js')
-rw-r--r--web_src/js/components/ActionRunStatus.vue21
-rw-r--r--web_src/js/components/ActivityHeatmap.vue28
-rw-r--r--web_src/js/components/ContextPopup.vue49
-rw-r--r--web_src/js/components/DashboardRepoList.vue298
-rw-r--r--web_src/js/components/DiffCommitSelector.vue143
-rw-r--r--web_src/js/components/DiffFileList.vue43
-rw-r--r--web_src/js/components/DiffFileTree.vue19
-rw-r--r--web_src/js/components/DiffFileTreeItem.vue46
-rw-r--r--web_src/js/components/PullRequestMergeForm.vue156
-rw-r--r--web_src/js/components/RepoActionView.vue241
-rw-r--r--web_src/js/components/RepoActivityTopAuthors.vue101
-rw-r--r--web_src/js/components/RepoBranchTagSelector.vue146
-rw-r--r--web_src/js/components/ScopedAccessTokenSelector.vue49
13 files changed, 661 insertions, 679 deletions
diff --git a/web_src/js/components/ActionRunStatus.vue b/web_src/js/components/ActionRunStatus.vue
index 1955decc1e..51a7745431 100644
--- a/web_src/js/components/ActionRunStatus.vue
+++ b/web_src/js/components/ActionRunStatus.vue
@@ -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>
diff --git a/web_src/js/components/ActivityHeatmap.vue b/web_src/js/components/ActivityHeatmap.vue
index 1b083ed134..96a6e68012 100644
--- a/web_src/js/components/ActivityHeatmap.vue
+++ b/web_src/js/components/ActivityHeatmap.vue
@@ -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>
diff --git a/web_src/js/components/ContextPopup.vue b/web_src/js/components/ContextPopup.vue
index b6852655f6..303e6d0c89 100644
--- a/web_src/js/components/ContextPopup.vue
+++ b/web_src/js/components/ContextPopup.vue
@@ -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>
diff --git a/web_src/js/components/DashboardRepoList.vue b/web_src/js/components/DashboardRepoList.vue
index 898362776b..5b8075f07a 100644
--- a/web_src/js/components/DashboardRepoList.vue
+++ b/web_src/js/components/DashboardRepoList.vue
@@ -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;
diff --git a/web_src/js/components/DiffCommitSelector.vue b/web_src/js/components/DiffCommitSelector.vue
index 283ef03ab9..48dc9d72ff 100644
--- a/web_src/js/components/DiffCommitSelector.vue
+++ b/web_src/js/components/DiffCommitSelector.vue
@@ -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;
diff --git a/web_src/js/components/DiffFileList.vue b/web_src/js/components/DiffFileList.vue
index 131be01811..103526d025 100644
--- a/web_src/js/components/DiffFileList.vue
+++ b/web_src/js/components/DiffFileList.vue
@@ -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)">&nbsp;</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)">&nbsp;</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>
diff --git a/web_src/js/components/DiffFileTree.vue b/web_src/js/components/DiffFileTree.vue
index e02222bde0..8ee86857ac 100644
--- a/web_src/js/components/DiffFileTree.vue
+++ b/web_src/js/components/DiffFileTree.vue
@@ -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>
diff --git a/web_src/js/components/DiffFileTreeItem.vue b/web_src/js/components/DiffFileTreeItem.vue
index d21afc42cb..553ab1464f 100644
--- a/web_src/js/components/DiffFileTreeItem.vue
+++ b/web_src/js/components/DiffFileTreeItem.vue
@@ -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;
diff --git a/web_src/js/components/PullRequestMergeForm.vue b/web_src/js/components/PullRequestMergeForm.vue
index 673773a91b..cca8b9dd6e 100644
--- a/web_src/js/components/PullRequestMergeForm.vue
+++ b/web_src/js/components/PullRequestMergeForm.vue
@@ -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 {
diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue
index 8d18ad2301..925ff7e087 100644
--- a/web_src/js/components/RepoActionView.vue
+++ b/web_src/js/components/RepoActionView.vue
@@ -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;
diff --git a/web_src/js/components/RepoActivityTopAuthors.vue b/web_src/js/components/RepoActivityTopAuthors.vue
index 294ee6f7bc..fe41218d88 100644
--- a/web_src/js/components/RepoActivityTopAuthors.vue
+++ b/web_src/js/components/RepoActivityTopAuthors.vue
@@ -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>
diff --git a/web_src/js/components/RepoBranchTagSelector.vue b/web_src/js/components/RepoBranchTagSelector.vue
index 1aba3b2935..b64b66d181 100644
--- a/web_src/js/components/RepoBranchTagSelector.vue
+++ b/web_src/js/components/RepoBranchTagSelector.vue
@@ -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;
diff --git a/web_src/js/components/ScopedAccessTokenSelector.vue b/web_src/js/components/ScopedAccessTokenSelector.vue
index b4b9b979ea..f6af7e447f 100644
--- a/web_src/js/components/ScopedAccessTokenSelector.vue
+++ b/web_src/js/components/ScopedAccessTokenSelector.vue
@@ -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>