* Add archived options to SearchRepository Signed-off-by: Andrew Thornton <art27@cantab.net> * Add only-private search Signed-off-by: Andrew Thornton <art27@cantab.net> * Add filter options and paging to dashboard repository page Signed-off-by: Andrew Thornton <art27@cantab.net> * swagger generate Signed-off-by: Andrew Thornton <art27@cantab.net> * fix-swagger-again Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @mrsdizzie also remember state Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv>tags/v1.13.0-dev
PriorityOwnerID int64 | PriorityOwnerID int64 | ||||
OrderBy SearchOrderBy | OrderBy SearchOrderBy | ||||
Private bool // Include private repositories in results | Private bool // Include private repositories in results | ||||
OnlyPrivate bool // Include only private repositories in results | |||||
StarredByID int64 | StarredByID int64 | ||||
AllPublic bool // Include also all public repositories of users and public organisations | AllPublic bool // Include also all public repositories of users and public organisations | ||||
AllLimited bool // Include also all public repositories of limited organisations | AllLimited bool // Include also all public repositories of limited organisations | ||||
// True -> include just mirrors | // True -> include just mirrors | ||||
// False -> include just non-mirrors | // False -> include just non-mirrors | ||||
Mirror util.OptionalBool | Mirror util.OptionalBool | ||||
// None -> include archived AND non-archived | |||||
// True -> include just archived | |||||
// False -> include just non-archived | |||||
Archived util.OptionalBool | |||||
// only search topic name | // only search topic name | ||||
TopicOnly bool | TopicOnly bool | ||||
// include description in keyword search | // include description in keyword search | ||||
} | } | ||||
} else { | } else { | ||||
// Not looking at private organisations | // Not looking at private organisations | ||||
// We should be able to see all non-private repositories that either: | |||||
cond = cond.And(builder.Eq{"is_private": false}) | |||||
accessCond := builder.Or( | |||||
// A. Aren't in organisations __OR__ | |||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})), | |||||
// B. Isn't a private or limited organisation. | |||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate})))) | |||||
cond = cond.And(accessCond) | |||||
// We should be able to see all non-private repositories that | |||||
// isn't in a private or limited organisation. | |||||
cond = cond.And( | |||||
builder.Eq{"is_private": false}, | |||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where( | |||||
builder.And( | |||||
builder.Eq{"type": UserTypeOrganization}, | |||||
builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}), | |||||
)))) | |||||
} | |||||
if opts.OnlyPrivate { | |||||
cond = cond.And( | |||||
builder.Or( | |||||
builder.Eq{"is_private": true}, | |||||
builder.In("owner_id", builder.Select("id").From("`user`").Where( | |||||
builder.And( | |||||
builder.Eq{"type": UserTypeOrganization}, | |||||
builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}), | |||||
))))) | |||||
} | } | ||||
if opts.Template != util.OptionalBoolNone { | if opts.Template != util.OptionalBoolNone { | ||||
cond = cond.And(accessibleRepositoryCondition(opts.Actor)) | cond = cond.And(accessibleRepositoryCondition(opts.Actor)) | ||||
} | } | ||||
if opts.Archived != util.OptionalBoolNone { | |||||
cond = cond.And(builder.Eq{"is_archived": opts.Archived == util.OptionalBoolTrue}) | |||||
} | |||||
switch opts.HasMilestones { | switch opts.HasMilestones { | ||||
case util.OptionalBoolTrue: | case util.OptionalBoolTrue: | ||||
cond = cond.And(builder.Gt{"num_milestones": 0}) | cond = cond.And(builder.Gt{"num_milestones": 0}) |
my_mirrors = My Mirrors | my_mirrors = My Mirrors | ||||
view_home = View %s | view_home = View %s | ||||
search_repos = Find a repository… | search_repos = Find a repository… | ||||
filter = Other Filters | |||||
show_archived = Archived | |||||
show_both_archived_unarchived = Showing both archived and unarchived | |||||
show_only_archived = Showing only archived | |||||
show_only_unarchived = Showing only unarchived | |||||
show_private = Private | |||||
show_both_private_public = Showing both public and private | |||||
show_only_private = Showing only private | |||||
show_only_public = Showing only public | |||||
issues.in_your_repos = In your repositories | issues.in_your_repos = In your repositories | ||||
// in: query | // in: query | ||||
// description: include private repositories this user has access to (defaults to true) | // description: include private repositories this user has access to (defaults to true) | ||||
// type: boolean | // type: boolean | ||||
// - name: onlyPrivate | |||||
// in: query | |||||
// description: only include private repositories this user has access to (defaults to false) | |||||
// type: boolean | |||||
// - name: template | // - name: template | ||||
// in: query | // in: query | ||||
// description: include template repositories this user has access to (defaults to true) | // description: include template repositories this user has access to (defaults to true) | ||||
// type: boolean | // type: boolean | ||||
// - name: archived | |||||
// in: query | |||||
// description: show only archived, non-archived or all repositories (defaults to all) | |||||
// type: boolean | |||||
// - name: mode | // - name: mode | ||||
// in: query | // in: query | ||||
// description: type of repository to search for. Supported values are | // description: type of repository to search for. Supported values are | ||||
TopicOnly: ctx.QueryBool("topic"), | TopicOnly: ctx.QueryBool("topic"), | ||||
Collaborate: util.OptionalBoolNone, | Collaborate: util.OptionalBoolNone, | ||||
Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")), | Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")), | ||||
OnlyPrivate: ctx.IsSigned && ctx.QueryBool("onlyPrivate"), | |||||
Template: util.OptionalBoolNone, | Template: util.OptionalBoolNone, | ||||
StarredByID: ctx.QueryInt64("starredBy"), | StarredByID: ctx.QueryInt64("starredBy"), | ||||
IncludeDescription: ctx.QueryBool("includeDesc"), | IncludeDescription: ctx.QueryBool("includeDesc"), | ||||
return | return | ||||
} | } | ||||
if ctx.Query("archived") != "" { | |||||
opts.Archived = util.OptionalBoolOf(ctx.QueryBool("archived")) | |||||
} | |||||
var sortMode = ctx.Query("sort") | var sortMode = ctx.Query("sort") | ||||
if len(sortMode) > 0 { | if len(sortMode) > 0 { | ||||
var sortOrder = ctx.Query("order") | var sortOrder = ctx.Query("order") |
"name": "private", | "name": "private", | ||||
"in": "query" | "in": "query" | ||||
}, | }, | ||||
{ | |||||
"type": "boolean", | |||||
"description": "only include private repositories this user has access to (defaults to false)", | |||||
"name": "onlyPrivate", | |||||
"in": "query" | |||||
}, | |||||
{ | { | ||||
"type": "boolean", | "type": "boolean", | ||||
"description": "include template repositories this user has access to (defaults to true)", | "description": "include template repositories this user has access to (defaults to true)", | ||||
"name": "template", | "name": "template", | ||||
"in": "query" | "in": "query" | ||||
}, | }, | ||||
{ | |||||
"type": "boolean", | |||||
"description": "show only archived, non-archived or all repositories (defaults to all)", | |||||
"name": "archived", | |||||
"in": "query" | |||||
}, | |||||
{ | { | ||||
"type": "string", | "type": "string", | ||||
"description": "type of repository to search for. Supported values are \"fork\", \"source\", \"mirror\" and \"collaborative\"", | "description": "type of repository to search for. Supported values are \"fork\", \"source\", \"mirror\" and \"collaborative\"", |
{{end}} | {{end}} | ||||
</h4> | </h4> | ||||
<div class="ui attached secondary segment repos-search"> | <div class="ui attached secondary segment repos-search"> | ||||
<div class="ui fluid icon input" :class="{loading: isLoading}"> | |||||
<div class="ui fluid right action left icon input" :class="{loading: isLoading}"> | |||||
<input @input="searchRepos(reposFilter)" v-model="searchQuery" ref="search" placeholder="{{.i18n.Tr "home.search_repos"}}"> | <input @input="searchRepos(reposFilter)" v-model="searchQuery" ref="search" placeholder="{{.i18n.Tr "home.search_repos"}}"> | ||||
<i class="search icon"></i> | <i class="search icon"></i> | ||||
<div class="ui dropdown button" title="{{.i18n.Tr "home.filter"}}"> | |||||
<i class="icon filter"></i> | |||||
<div class="menu"> | |||||
<div class="item"> | |||||
<a @click="toggleArchivedFilter()"> | |||||
<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.i18n.Tr "home.show_both_archived_unarchived"}}" v-if="archivedFilter === 'both'"> | |||||
<input type="checkbox"> | |||||
<label><i class="archive icon archived-icon"></i>{{.i18n.Tr "home.show_archived"}}</label> | |||||
</div> | |||||
<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.i18n.Tr "home.show_only_unarchived"}}" v-if="archivedFilter === 'unarchived'"> | |||||
<input type="checkbox"> | |||||
<label><i class="archive icon archived-icon"></i>{{.i18n.Tr "home.show_archived"}}</label> | |||||
</div> | |||||
<div class="ui checkbox" id="archivedFilterCheckbox" title="{{.i18n.Tr "home.show_only_archived"}}" v-if="archivedFilter === 'archived'"> | |||||
<input type="checkbox"> | |||||
<label><i class="archive icon archived-icon"></i>{{.i18n.Tr "home.show_archived"}}</label> | |||||
</div> | |||||
</a> | |||||
</div> | |||||
<div class="item"> | |||||
<a @click="togglePrivateFilter()"> | |||||
<div class="ui checkbox" id="privateFilterCheckbox" title="{{.i18n.Tr "home.show_both_private_public"}}" v-if="privateFilter === 'both'"> | |||||
<input type="checkbox"> | |||||
<label><svg class="svg octicon-lock" width="16" height="16" aria-hidden="true"><use xlink:href="#octicon-lock" /></svg>{{.i18n.Tr "home.show_private"}}</label> | |||||
</div> | |||||
<div class="ui checkbox" id="privateFilterCheckbox" title="{{.i18n.Tr "home.show_only_public"}}" v-if="privateFilter === 'public'"> | |||||
<input type="checkbox"> | |||||
<label><svg class="svg octicon-lock" width="16" height="16" aria-hidden="true"><use xlink:href="#octicon-lock" /></svg>{{.i18n.Tr "home.show_private"}}</label> | |||||
</div> | |||||
<div class="ui checkbox" id="privateFilterCheckbox" title="{{.i18n.Tr "home.show_only_private"}}" v-if="privateFilter === 'private'"> | |||||
<input type="checkbox"> | |||||
<label><svg class="svg octicon-lock" width="16" height="16" aria-hidden="true"><use xlink:href="#octicon-lock" /></svg>{{.i18n.Tr "home.show_private"}}</label> | |||||
</div> | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
<div class="ui secondary tiny pointing borderless menu center aligned grid repos-filter"> | <div class="ui secondary tiny pointing borderless menu center aligned grid repos-filter"> | ||||
<a class="item" :class="{active: reposFilter === 'all'}" @click="changeReposFilter('all')"> | <a class="item" :class="{active: reposFilter === 'all'}" @click="changeReposFilter('all')"> | ||||
</div> | </div> | ||||
<div class="ui attached table segment"> | <div class="ui attached table segment"> | ||||
<ul class="repo-owner-name-list"> | <ul class="repo-owner-name-list"> | ||||
<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo, reposFilter)"> | |||||
<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo)"> | |||||
<a :href="suburl + '/' + repo.full_name"> | <a :href="suburl + '/' + repo.full_name"> | ||||
<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="'#' + repoClass(repo)" /></svg> | <svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="'#' + repoClass(repo)" /></svg> | ||||
<strong class="text truncate item-name">${repo.full_name}</strong> | <strong class="text truncate item-name">${repo.full_name}</strong> | ||||
</a> | </a> | ||||
</li> | </li> | ||||
<li v-if="showMoreReposLink"> | <li v-if="showMoreReposLink"> | ||||
<a :href="moreReposLink">{{.i18n.Tr "home.show_more_repos"}}</a> | |||||
<div class="center"> | |||||
<div class="ui borderless pagination menu narrow"> | |||||
<a class="item navigation" :class="{'disabled': page === 1}" | |||||
@click="changePage(1)" title="{{$.i18n.Tr "admin.first_page"}}"> | |||||
<i class="angle double left icon"></i> | |||||
</a> | |||||
<a class="item navigation" :class="{'disabled': page === 1}" | |||||
@click="changePage(page - 1)" title="{{$.i18n.Tr "repo.issues.previous"}}"> | |||||
<i class="left arrow icon"></i> | |||||
</a> | |||||
<a class="active item">${page}</a> | |||||
<a class="item navigation" :class="{'disabled': page === finalPage}" | |||||
@click="changePage(page + 1)" title="{{$.i18n.Tr "repo.issues.next"}}"> | |||||
<i class="icon right arrow"></i> | |||||
</a> | |||||
<a class="item navigation" :class="{'disabled': page === finalPage}" | |||||
@click="changePage(finalPage)" title="{{$.i18n.Tr "admin.last_page"}}"> | |||||
<i class="angle double right icon"></i> | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</li> | </li> | ||||
</ul> | </ul> | ||||
</div> | </div> |
}, | }, | ||||
data() { | 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 = 'both'; | |||||
} | |||||
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 { | return { | ||||
tab: 'repos', | |||||
tab, | |||||
repos: [], | repos: [], | ||||
reposTotalCount: 0, | reposTotalCount: 0, | ||||
reposFilter: 'all', | |||||
searchQuery: '', | |||||
reposFilter, | |||||
archivedFilter, | |||||
privateFilter, | |||||
page, | |||||
finalPage: 1, | |||||
searchQuery, | |||||
isLoading: false, | isLoading: false, | ||||
staticPrefix: StaticUrlPrefix, | staticPrefix: StaticUrlPrefix, | ||||
counts: {}, | |||||
repoTypes: { | repoTypes: { | ||||
all: { | all: { | ||||
count: 0, | |||||
searchMode: '', | searchMode: '', | ||||
}, | }, | ||||
forks: { | forks: { | ||||
count: 0, | |||||
searchMode: 'fork', | searchMode: 'fork', | ||||
}, | }, | ||||
mirrors: { | mirrors: { | ||||
count: 0, | |||||
searchMode: 'mirror', | searchMode: 'mirror', | ||||
}, | }, | ||||
sources: { | sources: { | ||||
count: 0, | |||||
searchMode: 'source', | searchMode: 'source', | ||||
}, | }, | ||||
collaborative: { | collaborative: { | ||||
count: 0, | |||||
searchMode: 'collaborative', | searchMode: 'collaborative', | ||||
}, | }, | ||||
} | } | ||||
computed: { | computed: { | ||||
showMoreReposLink() { | showMoreReposLink() { | ||||
return this.repos.length > 0 && this.repos.length < this.repoTypes[this.reposFilter].count; | |||||
return this.repos.length > 0 && this.repos.length < this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`]; | |||||
}, | }, | ||||
searchURL() { | searchURL() { | ||||
return `${this.suburl}/api/v1/repos/search?sort=updated&order=desc&uid=${this.uid}&q=${this.searchQuery | return `${this.suburl}/api/v1/repos/search?sort=updated&order=desc&uid=${this.uid}&q=${this.searchQuery | ||||
}&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode | |||||
}${this.reposFilter !== 'all' ? '&exclusive=1' : ''}`; | |||||
}&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' ? '&onlyPrivate=true' : ''}${this.privateFilter === 'public' ? '&private=false' : '' | |||||
}`; | |||||
}, | }, | ||||
repoTypeCount() { | repoTypeCount() { | ||||
return this.repoTypes[this.reposFilter].count; | |||||
return this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`]; | |||||
} | } | ||||
}, | }, | ||||
mounted() { | mounted() { | ||||
this.searchRepos(this.reposFilter); | this.searchRepos(this.reposFilter); | ||||
$(this.$el).find('.poping.up').popup(); | |||||
$(this.$el).find('.dropdown').dropdown(); | |||||
this.setCheckboxes(); | |||||
const self = this; | const self = this; | ||||
Vue.nextTick(() => { | Vue.nextTick(() => { | ||||
self.$refs.search.focus(); | self.$refs.search.focus(); | ||||
methods: { | methods: { | ||||
changeTab(t) { | changeTab(t) { | ||||
this.tab = 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 = 'both'; | |||||
$('#archivedFilterCheckbox').checkbox('set indeterminate'); | |||||
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) { | changeReposFilter(filter) { | ||||
this.reposFilter = filter; | this.reposFilter = filter; | ||||
this.repos = []; | this.repos = []; | ||||
this.repoTypes[filter].count = 0; | |||||
this.searchRepos(filter); | |||||
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 === 'both') { | |||||
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}`); | |||||
} | |||||
window.history.replaceState({}, '', `?${params.toString()}`); | |||||
}, | |||||
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 = 'both'; | |||||
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(); | |||||
}, | |||||
showArchivedRepo(repo) { | |||||
switch (this.archivedFilter) { | |||||
case 'both': | |||||
return true; | |||||
case 'unarchived': | |||||
return !repo.archived; | |||||
case 'archived': | |||||
return repo.archived; | |||||
default: | |||||
return true; | |||||
} | |||||
}, | }, | ||||
showRepo(repo, filter) { | |||||
switch (filter) { | |||||
showPrivateRepo(repo) { | |||||
switch (this.privateFilter) { | |||||
case 'both': | |||||
return true; | |||||
case 'public': | |||||
return !repo.private; | |||||
case 'private': | |||||
return repo.private; | |||||
default: | |||||
return true; | |||||
} | |||||
}, | |||||
showFilteredRepo(repo) { | |||||
switch (this.reposFilter) { | |||||
case 'sources': | case 'sources': | ||||
return repo.owner.id === this.uid && !repo.mirror && !repo.fork; | return repo.owner.id === this.uid && !repo.mirror && !repo.fork; | ||||
case 'forks': | case 'forks': | ||||
} | } | ||||
}, | }, | ||||
searchRepos(reposFilter) { | |||||
showRepo(repo) { | |||||
return this.showArchivedRepo(repo) && this.showPrivateRepo(repo) && this.showFilteredRepo(repo); | |||||
}, | |||||
searchRepos() { | |||||
const self = this; | const self = this; | ||||
this.isLoading = true; | this.isLoading = true; | ||||
const searchedMode = this.repoTypes[reposFilter].searchMode; | |||||
const searchedMode = this.repoTypes[this.reposFilter].searchMode; | |||||
const searchedURL = this.searchURL; | const searchedURL = this.searchURL; | ||||
const searchedQuery = this.searchQuery; | const searchedQuery = this.searchQuery; | ||||
if (searchedURL === self.searchURL) { | if (searchedURL === self.searchURL) { | ||||
self.repos = result.data; | self.repos = result.data; | ||||
const count = request.getResponseHeader('X-Total-Count'); | const count = request.getResponseHeader('X-Total-Count'); | ||||
if (searchedQuery === '' && searchedMode === '') { | |||||
if (searchedQuery === '' && searchedMode === '' && self.archivedFilter === 'both') { | |||||
self.reposTotalCount = count; | self.reposTotalCount = count; | ||||
} | } | ||||
self.repoTypes[reposFilter].count = count; | |||||
Vue.set(self.counts, `${self.reposFilter}:${self.archivedFilter}:${self.privateFilter}`, count); | |||||
self.finalPage = Math.floor(count / self.searchLimit) + 1; | |||||
self.updateHistory(); | |||||
} | } | ||||
}).always(() => { | }).always(() => { | ||||
if (searchedURL === self.searchURL) { | if (searchedURL === self.searchURL) { |
} | } | ||||
.ui { | .ui { | ||||
&.left { | |||||
&.left:not(.action) { | |||||
float: left; | float: left; | ||||
} | } | ||||
&.right { | |||||
&.right:not(.action) { | |||||
float: right; | float: right; | ||||
} | } | ||||
display: none; | display: none; | ||||
} | } | ||||
} | } | ||||
&.narrow .item { | |||||
padding-left: 8px; | |||||
padding-right: 8px; | |||||
min-width: 1em; | |||||
text-align: center; | |||||
.icon { | |||||
margin-right: 0; | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#privateFilterCheckbox .svg { | |||||
color: #888888; | |||||
margin-right: .25rem; | |||||
} | |||||
.repo-owner-name-list { | .repo-owner-name-list { | ||||
.item-name { | .item-name { | ||||
max-width: 70%; | max-width: 70%; |