mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 00:20:25 +08:00 
			
		
		
		
	Improve "language stats" UI (#26968)
Before: * The layout is quite complex * The UI flickers when switch the stats (https://try.gitea.io/) After: * Simplify the code * The UI doesn't flicker
This commit is contained in:
		@@ -1,34 +1,31 @@
 | 
				
			|||||||
{{if and (not .HideRepoInfo) (not .IsBlame)}}
 | 
					{{if and (not .HideRepoInfo) (not .IsBlame)}}
 | 
				
			||||||
<div class="ui segments repository-summary{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}} repository-summary-language-stats{{end}} gt-mt-2 gt-mb-0">
 | 
					<div class="ui segments repository-summary gt-mt-2 gt-mb-0">
 | 
				
			||||||
	<div class="ui segment sub-menu repository-menu">
 | 
						<div class="ui segment sub-menu repository-menu">
 | 
				
			||||||
		<div class="ui two horizontal center list">
 | 
					 | 
				
			||||||
		{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo)}}
 | 
							{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo)}}
 | 
				
			||||||
				<div class="item{{if .PageIsCommits}} active{{end}}">
 | 
								<a class="item muted {{if .PageIsCommits}}active{{end}}" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}">
 | 
				
			||||||
					<a class="flex-text-inline" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}">{{svg "octicon-history"}} <b>{{.locale.PrettyNumber .CommitsCount}}</b> {{.locale.TrN .CommitsCount "repo.commit" "repo.commits"}}</a>
 | 
									{{svg "octicon-history"}} <b>{{.locale.PrettyNumber .CommitsCount}}</b> {{.locale.TrN .CommitsCount "repo.commit" "repo.commits"}}
 | 
				
			||||||
				</div>
 | 
								</a>
 | 
				
			||||||
				<div class="item{{if .PageIsBranches}} active{{end}}">
 | 
								<a class="item muted {{if .PageIsBranches}}active{{end}}" href="{{.RepoLink}}/branches">
 | 
				
			||||||
					<a class="flex-text-inline" href="{{.RepoLink}}/branches">{{svg "octicon-git-branch"}} <b>{{.locale.PrettyNumber .BranchesCount}}</b> {{.locale.TrN .BranchesCount "repo.branch" "repo.branches"}}</a>
 | 
									{{svg "octicon-git-branch"}} <b>{{.locale.PrettyNumber .BranchesCount}}</b> {{.locale.TrN .BranchesCount "repo.branch" "repo.branches"}}
 | 
				
			||||||
				</div>
 | 
								</a>
 | 
				
			||||||
			{{if $.Permission.CanRead $.UnitTypeCode}}
 | 
								{{if $.Permission.CanRead $.UnitTypeCode}}
 | 
				
			||||||
					<div class="item{{if .PageIsTagList}} active{{end}}">
 | 
									<a class="item muted {{if .PageIsTagList}}active{{end}}" href="{{.RepoLink}}/tags">
 | 
				
			||||||
						<a class="flex-text-inline" href="{{.RepoLink}}/tags">{{svg "octicon-tag"}} <b>{{.locale.PrettyNumber .NumTags}}</b> {{.locale.TrN .NumTags "repo.tag" "repo.tags"}}</a>
 | 
										{{svg "octicon-tag"}} <b>{{.locale.PrettyNumber .NumTags}}</b> {{.locale.TrN .NumTags "repo.tag" "repo.tags"}}
 | 
				
			||||||
					</div>
 | 
									</a>
 | 
				
			||||||
			{{end}}
 | 
								{{end}}
 | 
				
			||||||
				<div class="item" {{if not (eq .Repository.Size 0)}}data-tooltip-content="{{.Repository.SizeDetailsString}}"{{end}}>
 | 
								<span class="item not-mobile" {{if not (eq .Repository.Size 0)}}data-tooltip-content="{{.Repository.SizeDetailsString}}"{{end}}>
 | 
				
			||||||
				{{$fileSizeFormatted := FileSize .Repository.Size}}{{/* the formatted string is always "{val} {unit}" */}}
 | 
									{{$fileSizeFormatted := FileSize .Repository.Size}}{{/* the formatted string is always "{val} {unit}" */}}
 | 
				
			||||||
				{{$fileSizeFields := StringUtils.Split $fileSizeFormatted " "}}
 | 
									{{$fileSizeFields := StringUtils.Split $fileSizeFormatted " "}}
 | 
				
			||||||
					<span class="flex-text-inline">{{svg "octicon-database"}} <b>{{.locale.PrettyNumber (index $fileSizeFields 0)}}</b> {{index $fileSizeFields 1}}</span>
 | 
									{{svg "octicon-database"}} <b>{{.locale.PrettyNumber (index $fileSizeFields 0)}}</b> {{index $fileSizeFields 1}}
 | 
				
			||||||
				</div>
 | 
								</span>
 | 
				
			||||||
		{{end}}
 | 
							{{end}}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
	{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}}
 | 
						{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}}
 | 
				
			||||||
	<div class="ui segment sub-menu language-stats-details gt-hidden">
 | 
						<div class="ui segment sub-menu language-stats-details gt-hidden">
 | 
				
			||||||
		<div class="ui horizontal center list">
 | 
					 | 
				
			||||||
		{{range .LanguageStats}}
 | 
							{{range .LanguageStats}}
 | 
				
			||||||
			<div class="item gt-df gt-ac gt-jc">
 | 
							<div class="item">
 | 
				
			||||||
				<i class="color-icon gt-mr-3" style="background-color: {{.Color}}"></i>
 | 
								<i class="color-icon" style="background-color: {{.Color}}"></i>
 | 
				
			||||||
				<span class="gt-font-semibold gt-mr-3">
 | 
								<span class="gt-font-semibold">
 | 
				
			||||||
				{{if eq .Language "other"}}
 | 
									{{if eq .Language "other"}}
 | 
				
			||||||
					{{$.locale.Tr "repo.language_other"}}
 | 
										{{$.locale.Tr "repo.language_other"}}
 | 
				
			||||||
				{{else}}
 | 
									{{else}}
 | 
				
			||||||
@@ -39,10 +36,9 @@
 | 
				
			|||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		{{end}}
 | 
							{{end}}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	</div>
 | 
						<a class="ui segment language-stats show-panel toggle" data-panel=".repository-summary > .sub-menu">
 | 
				
			||||||
	<a class="ui segment language-stats">
 | 
					 | 
				
			||||||
		{{range .LanguageStats}}
 | 
							{{range .LanguageStats}}
 | 
				
			||||||
		<div class="bar" style="width: {{.Percentage}}%; background-color: {{.Color}}" data-tooltip-placement="top" data-tooltip-content={{.Language}}> </div>
 | 
							<div class="bar" style="width: {{.Percentage}}%; background-color: {{.Color}}" data-tooltip-placement="top" data-tooltip-content={{.Language}}></div>
 | 
				
			||||||
		{{end}}
 | 
							{{end}}
 | 
				
			||||||
	</a>
 | 
						</a>
 | 
				
			||||||
	{{end}}
 | 
						{{end}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,6 @@
 | 
				
			|||||||
.repository .data-table .line-num,
 | 
					.repository .data-table .line-num,
 | 
				
			||||||
.repository .diff-file-box .file-body.file-code .lines-num,
 | 
					.repository .diff-file-box .file-body.file-code .lines-num,
 | 
				
			||||||
.repository .diff-file-box .code-diff tbody tr .lines-type-marker,
 | 
					.repository .diff-file-box .code-diff tbody tr .lines-type-marker {
 | 
				
			||||||
.repository .repository-summary .segment.language-stats {
 | 
					 | 
				
			||||||
  -webkit-touch-callout: none;
 | 
					 | 
				
			||||||
  -webkit-user-select: none;
 | 
					 | 
				
			||||||
  user-select: none;
 | 
					  user-select: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1943,47 +1940,6 @@
 | 
				
			|||||||
  border-bottom: 1px solid var(--color-warning-border);
 | 
					  border-bottom: 1px solid var(--color-warning-border);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.repository .ui.segment.sub-menu {
 | 
					 | 
				
			||||||
  padding: 7px;
 | 
					 | 
				
			||||||
  line-height: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .ui.segment.sub-menu .list {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  align-items: stretch;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .ui.segment.sub-menu .list .item {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  color: var(--color-text);
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  align-items: center;
 | 
					 | 
				
			||||||
  justify-content: center;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .ui.segment.sub-menu .list .item:first-of-type {
 | 
					 | 
				
			||||||
  border-radius: var(--border-radius) 0 0 var(--border-radius);
 | 
					 | 
				
			||||||
  padding-left: 0.25rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .ui.segment.sub-menu .list .item:last-of-type {
 | 
					 | 
				
			||||||
  border-radius: 0 var(--border-radius) var(--border-radius) 0;
 | 
					 | 
				
			||||||
  padding-right: 0.25rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .ui.segment.sub-menu .list .item a {
 | 
					 | 
				
			||||||
  color: var(--color-text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .ui.segment.sub-menu .list .item a:hover {
 | 
					 | 
				
			||||||
  color: var(--color-primary-light-2);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .ui.segment.sub-menu .list .item.active {
 | 
					 | 
				
			||||||
  background: var(--color-secondary);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .segment.reactions.dropdown .menu,
 | 
					.repository .segment.reactions.dropdown .menu,
 | 
				
			||||||
.repository .select-reaction.dropdown .menu {
 | 
					.repository .select-reaction.dropdown .menu {
 | 
				
			||||||
  right: 0 !important;
 | 
					  right: 0 !important;
 | 
				
			||||||
@@ -2081,49 +2037,39 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.repository .repository-summary {
 | 
					.repository .repository-summary {
 | 
				
			||||||
  box-shadow: none !important;
 | 
					  box-shadow: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.repository .repository-summary .segment.language-stats-details,
 | 
					.repository .repository-summary .segment.sub-menu {
 | 
				
			||||||
.repository .repository-summary .segment.repository-summary {
 | 
					  border: none;
 | 
				
			||||||
  border-top: none;
 | 
					 | 
				
			||||||
  background: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .repository-summary .segment.language-stats-details .item {
 | 
					 | 
				
			||||||
  white-space: nowrap;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .repository-summary .segment.language-stats {
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
  height: 11px;
 | 
					 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  white-space: nowrap;
 | 
					  align-items: center;
 | 
				
			||||||
  width: 100%;
 | 
					  padding: 0 0.5em; /* make the UI look better for narrow (mobile) view */
 | 
				
			||||||
  border-radius: 0;
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.repository .repository-summary .sub-menu .item {
 | 
				
			||||||
 | 
					  flex: 1;
 | 
				
			||||||
 | 
					  height: 30px;
 | 
				
			||||||
 | 
					  line-height: var(--line-height-default);
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  gap: 0.25em;
 | 
				
			||||||
 | 
					  padding: 0 0.25em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.repository .repository-summary .sub-menu .item.active {
 | 
				
			||||||
 | 
					  background: var(--color-secondary);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media (max-width: 767.98px) {
 | 
					 | 
				
			||||||
.repository .repository-summary .segment.language-stats {
 | 
					.repository .repository-summary .segment.language-stats {
 | 
				
			||||||
    display: none;
 | 
					  display: flex;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .repository-summary .segment.language-stats .bar {
 | 
					 | 
				
			||||||
  white-space: nowrap;
 | 
					 | 
				
			||||||
  border: 0;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					  padding: 0;
 | 
				
			||||||
  margin: 0;
 | 
					  height: 10px;
 | 
				
			||||||
  height: 100%;
 | 
					  white-space: nowrap;
 | 
				
			||||||
}
 | 
					  border-radius: 0 0 3px 3px !important;
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
.repository .repository-menu {
 | 
					 | 
				
			||||||
  padding: 0 !important;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.repository .repository-menu .item {
 | 
					 | 
				
			||||||
  padding-top: 9px !important;
 | 
					 | 
				
			||||||
  padding-bottom: 9px !important;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#cite-repo-modal #citation-panel {
 | 
					#cite-repo-modal #citation-panel {
 | 
				
			||||||
@@ -2924,18 +2870,6 @@ tbody.commit-list {
 | 
				
			|||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* prevent page shaking on language bar click */
 | 
					 | 
				
			||||||
.repository-summary-language-stats {
 | 
					 | 
				
			||||||
  height: 48px;
 | 
					 | 
				
			||||||
  overflow: hidden;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@media (max-width: 767.98px) {
 | 
					 | 
				
			||||||
  .repository-summary-language-stats {
 | 
					 | 
				
			||||||
    height: auto;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.ui.form .right .ui.button {
 | 
					.ui.form .right .ui.button {
 | 
				
			||||||
  margin-left: 0.25em;
 | 
					  margin-left: 0.25em;
 | 
				
			||||||
  margin-right: 0;
 | 
					  margin-right: 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -388,9 +388,9 @@ export function initGlobalButtons() {
 | 
				
			|||||||
    e.preventDefault();
 | 
					    e.preventDefault();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $('.show-panel.button').on('click', function (e) {
 | 
					  $('.show-panel').on('click', function (e) {
 | 
				
			||||||
    // a '.show-panel.button' can show a panel, by `data-panel="selector"`
 | 
					    // a '.show-panel' element can show a panel, by `data-panel="selector"`
 | 
				
			||||||
    // if the button is a "toggle" button, it toggles the panel
 | 
					    // if it has "toggle" class, it toggles the panel
 | 
				
			||||||
    e.preventDefault();
 | 
					    e.preventDefault();
 | 
				
			||||||
    const sel = $(this).attr('data-panel');
 | 
					    const sel = $(this).attr('data-panel');
 | 
				
			||||||
    if (this.classList.contains('toggle')) {
 | 
					    if (this.classList.contains('toggle')) {
 | 
				
			||||||
@@ -400,8 +400,8 @@ export function initGlobalButtons() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $('.hide-panel.button').on('click', function (e) {
 | 
					  $('.hide-panel').on('click', function (e) {
 | 
				
			||||||
    // a `.hide-panel.button` can hide a panel, by `data-panel="selector"` or `data-panel-closest="selector"`
 | 
					    // a `.hide-panel` element can hide a panel, by `data-panel="selector"` or `data-panel-closest="selector"`
 | 
				
			||||||
    e.preventDefault();
 | 
					    e.preventDefault();
 | 
				
			||||||
    let sel = $(this).attr('data-panel');
 | 
					    let sel = $(this).attr('data-panel');
 | 
				
			||||||
    if (sel) {
 | 
					    if (sel) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import $ from 'jquery';
 | 
					import $ from 'jquery';
 | 
				
			||||||
import {hideElem, showElem, toggleElem} from '../utils/dom.js';
 | 
					import {hideElem, showElem} from '../utils/dom.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const {csrfToken} = window.config;
 | 
					const {csrfToken} = window.config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -91,13 +91,3 @@ export function initRepoCommonFilterSearchDropdown(selector) {
 | 
				
			|||||||
    message: {noResults: $dropdown.attr('data-no-results')},
 | 
					    message: {noResults: $dropdown.attr('data-no-results')},
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
export function initRepoCommonLanguageStats() {
 | 
					 | 
				
			||||||
  // Language stats
 | 
					 | 
				
			||||||
  if ($('.language-stats').length > 0) {
 | 
					 | 
				
			||||||
    $('.language-stats').on('click', (e) => {
 | 
					 | 
				
			||||||
      e.preventDefault();
 | 
					 | 
				
			||||||
      toggleElem($('.language-stats-details, .repository-menu'));
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,6 @@ import {htmlEscape} from 'escape-goat';
 | 
				
			|||||||
import {initRepoBranchTagSelector} from '../components/RepoBranchTagSelector.vue';
 | 
					import {initRepoBranchTagSelector} from '../components/RepoBranchTagSelector.vue';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown,
 | 
					  initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown,
 | 
				
			||||||
  initRepoCommonLanguageStats,
 | 
					 | 
				
			||||||
} from './repo-common.js';
 | 
					} from './repo-common.js';
 | 
				
			||||||
import {initCitationFileCopyContent} from './citation.js';
 | 
					import {initCitationFileCopyContent} from './citation.js';
 | 
				
			||||||
import {initCompLabelEdit} from './comp/LabelEdit.js';
 | 
					import {initCompLabelEdit} from './comp/LabelEdit.js';
 | 
				
			||||||
@@ -525,7 +524,6 @@ export function initRepository() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  initRepoCloneLink();
 | 
					  initRepoCloneLink();
 | 
				
			||||||
  initCitationFileCopyContent();
 | 
					  initCitationFileCopyContent();
 | 
				
			||||||
  initRepoCommonLanguageStats();
 | 
					 | 
				
			||||||
  initRepoSettingBranches();
 | 
					  initRepoSettingBranches();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Issues
 | 
					  // Issues
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user