Skip to content

Commit

Permalink
Fix and improve dashboard repo UI (#2285)
Browse files Browse the repository at this point in the history
* Fix and improve dashboard repo UI

* Change order of scripts loading

* Remove "mirror" tab

* Remove single tab panel for "org user"

* Add localization strings

* Create vue component and change event for search

* Add "mirrors" filter
  • Loading branch information
Morlinest authored and lunny committed Aug 17, 2017
1 parent 722bcef commit 951fb57
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 121 deletions.
5 changes: 5 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ your_profile = Your Profile
your_starred = Your Starred
your_settings = Your Settings

all = All
sources = Sources
mirrors = Mirrors
collaborative = Collaborative

activities = Activities
pull_requests = Pull Requests
issues = Issues
Expand Down
11 changes: 11 additions & 0 deletions public/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,17 @@ footer .ui.language .menu {
padding-right: 30px !important;
}
}
[v-cloak] {
display: none !important;
}
.repos-search {
padding-bottom: 0 !important;
}
.repos-filter {
margin-top: 0 !important;
border-bottom-width: 0 !important;
margin-bottom: 2px !important;
}
.markdown:not(code) {
overflow: hidden;
font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
Expand Down
102 changes: 82 additions & 20 deletions public/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1655,29 +1655,45 @@ $(function () {
});
});

function initDashboardSearch() {
var el = document.getElementById('dashboard-repo-search');
if (!el) {
return;
}
function initVueComponents(){
var vueDelimeters = ['${', '}'];

new Vue({
delimiters: ['${', '}'],
el: el,
Vue.component('repo-search', {
delimiters: vueDelimeters,
template: '#repo-search-template',

data: {
tab: 'repos',
repos: [],
searchQuery: '',
suburl: document.querySelector('meta[name=_suburl]').content,
uid: document.querySelector('meta[name=_context_uid]').content
props: {
searchLimit: {
type: Number,
default: 10
},
suburl: {
type: String,
required: true
},
uid: {
type: Number,
required: true
},
},

data: function() {
return {
tab: 'repos',
repos: [],
reposTotal: 0,
reposFilter: 'all',
searchQuery: '',
isLoading: false
}
},

mounted: function() {
this.searchRepos();

var self = this;
Vue.nextTick(function() {
document.querySelector('#search_repo').focus();
self.$refs.search.focus();
});
},

Expand All @@ -1686,19 +1702,45 @@ function initDashboardSearch() {
this.tab = t;
},

searchKeyUp: function() {
this.searchRepos();
changeReposFilter: function(filter) {
this.reposFilter = filter;
},

showRepo: function(repo, filter) {
switch (filter) {
case 'sources':
return repo.owner.id == this.uid && !repo.mirror && !repo.fork;
case 'forks':
return repo.owner.id == this.uid && !repo.mirror && repo.fork;
case 'mirrors':
return repo.mirror;
case 'collaborative':
return repo.owner.id != this.uid;
default:
return true;
}
},

searchRepos: function() {
var self = this;
$.getJSON(this.searchURL(), function(result) {
self.repos = result.data;
this.isLoading = true;
var searchedQuery = this.searchQuery;
$.getJSON(this.searchURL(), function(result, textStatus, request) {
if (searchedQuery == self.searchQuery) {
self.repos = result.data;
if (searchedQuery == "") {
self.reposTotal = request.getResponseHeader('X-Total-Count');
}
}
}).always(function() {
if (searchedQuery == self.searchQuery) {
self.isLoading = false;
}
});
},

searchURL: function() {
return this.suburl + '/api/v1/repos/search?uid=' + this.uid + '&q=' + this.searchQuery;
return this.suburl + '/api/v1/repos/search?uid=' + this.uid + '&q=' + this.searchQuery + '&limit=' + this.searchLimit;
},

repoClass: function(repo) {
Expand All @@ -1713,5 +1755,25 @@ function initDashboardSearch() {
}
}
}
})
}

function initDashboardSearch() {
var el = document.getElementById('dashboard-repo-search');
if (!el) {
return;
}

initVueComponents();

new Vue({
delimiters: ['${', '}'],
el: el,

data: {
searchLimit: document.querySelector('meta[name=_search_limit]').content,
suburl: document.querySelector('meta[name=_suburl]').content,
uid: document.querySelector('meta[name=_context_uid]').content,
},
});
}
14 changes: 14 additions & 0 deletions public/less/_base.less
Original file line number Diff line number Diff line change
Expand Up @@ -464,3 +464,17 @@ footer {
padding-right: 30px !important;
}
}

[v-cloak] {
display: none !important;
}

.repos-search {
padding-bottom: 0 !important;
}

.repos-filter {
margin-top: 0 !important;
border-bottom-width: 0 !important;
margin-bottom: 2px !important;
}
2 changes: 2 additions & 0 deletions routers/api/v1/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package repo

import (
"fmt"
"strings"

api "code.gitea.io/sdk/gitea"
Expand Down Expand Up @@ -91,6 +92,7 @@ func Search(ctx *context.APIContext) {
}

ctx.SetLinkHeader(int(count), setting.API.MaxResponseItems)
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", count))
ctx.JSON(200, api.SearchResults{
OK: true,
Data: results,
Expand Down
1 change: 1 addition & 0 deletions routers/user/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ func Dashboard(ctx *context.Context) {
ctx.Data["Title"] = ctxUser.DisplayName() + " - " + ctx.Tr("dashboard")
ctx.Data["PageIsDashboard"] = true
ctx.Data["PageIsNews"] = true
ctx.Data["SearchLimit"] = setting.UI.User.RepoPagingNum

// Only user can have collaborative repositories.
if !ctxUser.IsOrganization() {
Expand Down
8 changes: 4 additions & 4 deletions templates/base/footer.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@
<script src="{{AppSubUrl}}/js/draw.js"></script>
{{end}}

<!-- JavaScript -->
<script src="{{AppSubUrl}}/js/semantic-2.2.1.min.js"></script>
<script src="{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}"></script>

<!-- Third-party libraries -->
{{if .RequireHighlightJS}}
<script src="{{AppSubUrl}}/plugins/highlight-9.11.0/highlight.pack.js"></script>
Expand All @@ -66,5 +62,9 @@
<script src="{{AppSubUrl}}/js/libs/emojify-1.1.0.min.js"></script>
<script src="{{AppSubUrl}}/js/libs/clipboard-1.5.9.min.js"></script>
<script src="{{AppSubUrl}}/js/libs/vue.min.js"></script>

<!-- JavaScript -->
<script src="{{AppSubUrl}}/js/semantic-2.2.1.min.js"></script>
<script src="{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}"></script>
</body>
</html>
3 changes: 3 additions & 0 deletions templates/base/head.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
{{if .ContextUser}}
<meta name="_context_uid" content="{{.ContextUser.ID}}" />
{{end}}
{{if .SearchLimit}}
<meta name="_search_limit" content="{{.SearchLimit}}" />
{{end}}
{{if .GoGetImport}}
<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}">
<meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}">
Expand Down
99 changes: 2 additions & 97 deletions templates/user/dashboard/dashboard.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,105 +8,10 @@
{{template "user/dashboard/feeds" .}}
</div>
<div id="dashboard-repo-search" class="six wide column">
<div class="ui {{if not .ContextUser.IsOrganization}}three{{else}}two{{end}} item stackable tabable menu">
<a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{.i18n.Tr "repository"}}</a>
{{if not .ContextUser.IsOrganization}}
<a :class="{item: true, active: tab === 'orgs'}" @click="changeTab('orgs')">{{.i18n.Tr "organization"}}</a>
{{end}}
<a :class="{item: true, active: tab === 'mirrors'}" @click="changeTab('mirrors')">{{.i18n.Tr "mirror"}}</a>
</div>
<div v-if="tab === 'repos'" class="ui tab active list">
<div class="ui fluid input">
<input @keyUp="searchKeyUp" v-model="searchQuery" id="search_repo" placeholder="{{.i18n.Tr "home.search_repos"}}">
</div>
<h4 class="ui top attached header">
{{.i18n.Tr "home.my_repos"}} <span class="ui grey label">{{.ContextUser.NumRepos}}</span>
<div class="ui right">
<a class="poping up" href="{{AppSubUrl}}/repo/create" data-content="{{.i18n.Tr "new_repo"}}" data-variation="tiny inverted" data-position="left center">
<i class="plus icon"></i>
<span class="sr-only">{{.i18n.Tr "new_repo"}}</span>
</a>
</div>
</h4>
<div class="ui attached table segment">
<ul class="repo-owner-name-list">
<li v-for="repo in repos" :class="{'private': repo.private}">
<a :href="'{{AppSubUrl}}/' + repo.full_name">
<i :class="repoClass(repo)"></i>
<strong class="text truncate item-name">${ repo.full_name }</strong>
<span class="ui right text light grey">
${ repo.stars_count } <i class="octicon octicon-star rear"></i>
</span>
</a>
</li>
{{if gt .ContextUser.NumRepos .MaxShowRepoNum}}
<li>
<a href="{{.ContextUser.HomeLink}}">{{.i18n.Tr "home.show_more_repos"}}</a>
</li>
{{end}}
</ul>
</div>
</div>

{{if not .ContextUser.IsOrganization}}
<div v-if="tab === 'orgs'" class="ui tab active list">
<h4 class="ui top attached header">
{{.i18n.Tr "home.my_orgs"}} <span class="ui grey label">{{.ContextUser.GetOrganizationCount}}</span>
<div class="ui right">
{{if .SignedUser.CanCreateOrganization}}
<a class="poping up" href="{{AppSubUrl}}/org/create" data-content="{{.i18n.Tr "new_org"}}" data-variation="tiny inverted" data-position="left center">
<i class="plus icon"></i>
<span class="sr-only">{{.i18n.Tr "new_org"}}</span>
</a>
{{end}}
</div>
</h4>
<div class="ui attached table segment">
<ul class="repo-owner-name-list">
{{range .ContextUser.Orgs}}
<li>
<a href="{{AppSubUrl}}/{{.Name}}">
<i class="octicon octicon-organization"></i>
<strong class="text truncate item-name">{{.Name}}</strong>
<span class="ui right text light grey">
{{.NumRepos}} <i class="octicon octicon-repo rear"></i>
</span>
</a>
</li>
{{end}}
</ul>
</div>
</div>
{{end}}

<div v-if="tab === 'mirrors'" class="ui tab active list">
<h4 class="ui top attached header">
{{.i18n.Tr "home.my_mirrors"}} <span class="ui grey label">{{.MirrorCount}}</span>
<div class="ui right">
<a class="poping up" href="{{AppSubUrl}}/repo/migrate?mirror=1" data-content="{{.i18n.Tr "new_mirror"}}" data-variation="tiny inverted" data-position="left center">
<i class="plus icon"></i>
<span class="sr-only">{{.i18n.Tr "new_mirror"}}</span>
</a>
</div>
</h4>
<div class="ui attached table segment">
<ul class="repo-owner-name-list">
{{range .Mirrors}}
<li {{if .IsPrivate}}class="private"{{end}}>
<a href="{{AppSubUrl}}/{{$.ContextUser.Name}}/{{.Name}}">
<i class="octicon octicon-repo-clone"></i>
<strong class="text truncate item-name">{{.Name}}</strong>
<span class="ui right text light grey">
{{.Interval}}H <i class="octicon octicon-sync rear"></i>
</span>
</a>
</li>
{{end}}
</ul>
</div>
</div>
<repo-search :search-limit="searchLimit" :suburl="suburl" :uid="uid"><i class="fa fa-spinner fa-spin"></i></repo-search>
</div>
</div>
</div>
</div>
{{template "user/dashboard/repo-search" .}}
{{template "base/footer" .}}
Loading

0 comments on commit 951fb57

Please sign in to comment.