1
0
Fork 0
forked from kevadesu/forgejo
RSCC-Forge/web_src/js/components/DashboardRepoList.js
zeripath e2a59c57fc
Fix dashboard repolist alignment and repolisting ()
Unfortunately  broke the restriction of the dashboard repolist to
the user's repos because it stopped passing in the uid for the current
user. This PR restores this.

There is also a weird alignment problem - not caused by that PR - where
the menu items in the repolist spread over multiple lines. This PR
simply reduces the padding on these items and switches the justification
of the flex elements to space-evenly.

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2021-10-19 12:38:33 +08:00

369 lines
10 KiB
JavaScript

import Vue from 'vue';
import {initVueSvg, vueDelimiters} from './VueComponentLoader.js';
const {AppSubUrl, AssetUrlPrefix, pageData} = window.config;
function initVueComponents() {
Vue.component('repo-search', {
delimiters: vueDelimiters,
props: {
searchLimit: {
type: Number,
default: 10
},
subUrl: {
type: String,
required: true
},
uid: {
type: Number,
default: 0
},
teamId: {
type: Number,
required: false,
default: 0
},
organizations: {
type: Array,
default: () => [],
},
isOrganization: {
type: Boolean,
default: true
},
canCreateOrganization: {
type: Boolean,
default: false
},
organizationsTotalCount: {
type: Number,
default: 0
},
moreReposLink: {
type: String,
default: ''
}
},
data() {
const params = new URLSearchParams(window.location.search);
let tab = params.get('repo-search-tab');
if (!tab) {
tab = 'repos';
}
let reposFilter = params.get('repo-search-filter');
if (!reposFilter) {
reposFilter = 'all';
}
let privateFilter = params.get('repo-search-private');
if (!privateFilter) {
privateFilter = 'both';
}
let archivedFilter = params.get('repo-search-archived');
if (!archivedFilter) {
archivedFilter = 'unarchived';
}
let searchQuery = params.get('repo-search-query');
if (!searchQuery) {
searchQuery = '';
}
let page = 1;
try {
page = parseInt(params.get('repo-search-page'));
} catch {
// noop
}
if (!page) {
page = 1;
}
return {
tab,
repos: [],
reposTotalCount: 0,
reposFilter,
archivedFilter,
privateFilter,
page,
finalPage: 1,
searchQuery,
isLoading: false,
staticPrefix: AssetUrlPrefix,
counts: {},
repoTypes: {
all: {
searchMode: '',
},
forks: {
searchMode: 'fork',
},
mirrors: {
searchMode: 'mirror',
},
sources: {
searchMode: 'source',
},
collaborative: {
searchMode: 'collaborative',
},
}
};
},
computed: {
// used in `repolist.tmpl`
showMoreReposLink() {
return this.repos.length > 0 && this.repos.length < this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`];
},
searchURL() {
return `${this.subUrl}/api/v1/repos/search?sort=updated&order=desc&uid=${this.uid}&team_id=${this.teamId}&q=${this.searchQuery
}&page=${this.page}&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode
}${this.reposFilter !== 'all' ? '&exclusive=1' : ''
}${this.archivedFilter === 'archived' ? '&archived=true' : ''}${this.archivedFilter === 'unarchived' ? '&archived=false' : ''
}${this.privateFilter === 'private' ? '&is_private=true' : ''}${this.privateFilter === 'public' ? '&is_private=false' : ''
}`;
},
repoTypeCount() {
return this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`];
}
},
mounted() {
this.changeReposFilter(this.reposFilter);
$(this.$el).find('.poping.up').popup();
$(this.$el).find('.dropdown').dropdown();
this.setCheckboxes();
Vue.nextTick(() => {
this.$refs.search.focus();
});
},
methods: {
changeTab(t) {
this.tab = t;
this.updateHistory();
},
setCheckboxes() {
switch (this.archivedFilter) {
case 'unarchived':
$('#archivedFilterCheckbox').checkbox('set unchecked');
break;
case 'archived':
$('#archivedFilterCheckbox').checkbox('set checked');
break;
case 'both':
$('#archivedFilterCheckbox').checkbox('set indeterminate');
break;
default:
this.archivedFilter = 'unarchived';
$('#archivedFilterCheckbox').checkbox('set unchecked');
break;
}
switch (this.privateFilter) {
case 'public':
$('#privateFilterCheckbox').checkbox('set unchecked');
break;
case 'private':
$('#privateFilterCheckbox').checkbox('set checked');
break;
case 'both':
$('#privateFilterCheckbox').checkbox('set indeterminate');
break;
default:
this.privateFilter = 'both';
$('#privateFilterCheckbox').checkbox('set indeterminate');
break;
}
},
changeReposFilter(filter) {
this.reposFilter = filter;
this.repos = [];
this.page = 1;
Vue.set(this.counts, `${filter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.searchRepos();
},
updateHistory() {
const params = new URLSearchParams(window.location.search);
if (this.tab === 'repos') {
params.delete('repo-search-tab');
} else {
params.set('repo-search-tab', this.tab);
}
if (this.reposFilter === 'all') {
params.delete('repo-search-filter');
} else {
params.set('repo-search-filter', this.reposFilter);
}
if (this.privateFilter === 'both') {
params.delete('repo-search-private');
} else {
params.set('repo-search-private', this.privateFilter);
}
if (this.archivedFilter === 'unarchived') {
params.delete('repo-search-archived');
} else {
params.set('repo-search-archived', this.archivedFilter);
}
if (this.searchQuery === '') {
params.delete('repo-search-query');
} else {
params.set('repo-search-query', this.searchQuery);
}
if (this.page === 1) {
params.delete('repo-search-page');
} else {
params.set('repo-search-page', `${this.page}`);
}
const queryString = params.toString();
if (queryString) {
window.history.replaceState({}, '', `?${queryString}`);
} else {
window.history.replaceState({}, '', window.location.pathname);
}
},
toggleArchivedFilter() {
switch (this.archivedFilter) {
case 'both':
this.archivedFilter = 'unarchived';
break;
case 'unarchived':
this.archivedFilter = 'archived';
break;
case 'archived':
this.archivedFilter = 'both';
break;
default:
this.archivedFilter = 'unarchived';
break;
}
this.page = 1;
this.repos = [];
this.setCheckboxes();
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.searchRepos();
},
togglePrivateFilter() {
switch (this.privateFilter) {
case 'both':
this.privateFilter = 'public';
break;
case 'public':
this.privateFilter = 'private';
break;
case 'private':
this.privateFilter = 'both';
break;
default:
this.privateFilter = 'both';
break;
}
this.page = 1;
this.repos = [];
this.setCheckboxes();
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.searchRepos();
},
changePage(page) {
this.page = page;
if (this.page > this.finalPage) {
this.page = this.finalPage;
}
if (this.page < 1) {
this.page = 1;
}
this.repos = [];
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, 0);
this.searchRepos();
},
searchRepos() {
this.isLoading = true;
if (!this.reposTotalCount) {
const totalCountSearchURL = `${this.subUrl}/api/v1/repos/search?sort=updated&order=desc&uid=${this.uid}&team_id=${this.teamId}&q=&page=1&mode=`;
$.getJSON(totalCountSearchURL, (_result, _textStatus, request) => {
this.reposTotalCount = request.getResponseHeader('X-Total-Count');
});
}
const searchedMode = this.repoTypes[this.reposFilter].searchMode;
const searchedURL = this.searchURL;
const searchedQuery = this.searchQuery;
$.getJSON(searchedURL, (result, _textStatus, request) => {
if (searchedURL === this.searchURL) {
this.repos = result.data;
const count = request.getResponseHeader('X-Total-Count');
if (searchedQuery === '' && searchedMode === '' && this.archivedFilter === 'both') {
this.reposTotalCount = count;
}
Vue.set(this.counts, `${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`, count);
this.finalPage = Math.ceil(count / this.searchLimit);
this.updateHistory();
}
}).always(() => {
if (searchedURL === this.searchURL) {
this.isLoading = false;
}
});
},
repoIcon(repo) {
if (repo.fork) {
return 'octicon-repo-forked';
} else if (repo.mirror) {
return 'octicon-mirror';
} else if (repo.template) {
return `octicon-repo-template`;
} else if (repo.private) {
return 'octicon-lock';
} else if (repo.internal) {
return 'octicon-repo';
}
return 'octicon-repo';
}
}
});
}
export function initDashboardRepoList() {
const el = document.getElementById('dashboard-repo-list');
const dashboardRepoListData = pageData.dashboardRepoList || null;
if (!el || !dashboardRepoListData) return;
initVueSvg();
initVueComponents();
new Vue({
el,
delimiters: vueDelimiters,
data: () => {
return {
searchLimit: dashboardRepoListData.searchLimit || 0,
subUrl: AppSubUrl,
uid: dashboardRepoListData.uid || 0,
};
},
});
}