mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Rework notifications list (#24812)
- Replace `<table>` with flexbox - Add issue modification time and issue number - Remove big title - Replace tabs with menu items - Add clicked item deletion on back button cache restoration --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		| @@ -27,7 +27,7 @@ | ||||
| 							</td> | ||||
| 							<td class="right aligned overflow-visible"> | ||||
| 								{{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted)}} | ||||
| 									<button class="ui button button-ghost show-create-branch-modal gt-mx-3" | ||||
| 									<button class="ui button button-ghost show-create-branch-modal gt-p-3" | ||||
| 										data-modal="#create-branch-modal" | ||||
| 										data-branch-from="{{$.DefaultBranch}}" | ||||
| 										data-branch-from-urlcomponent="{{PathEscapeSegments $.DefaultBranch}}" | ||||
| @@ -37,12 +37,12 @@ | ||||
| 									</button> | ||||
| 								{{end}} | ||||
| 								{{if .EnableFeed}} | ||||
| 									<a role="button" class="ui button button-ghost gt-mx-3" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DefaultBranch}}"> | ||||
| 									<a role="button" class="ui button button-ghost gt-p-3" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DefaultBranch}}"> | ||||
| 										{{svg "octicon-rss"}} | ||||
| 									</a> | ||||
| 								{{end}} | ||||
| 								{{if not $.DisableDownloadSourceArchives}} | ||||
| 									<div class="ui dropdown button button-ghost gt-mx-3"  data-tooltip-content="{{$.locale.Tr "repo.branch.download" ($.DefaultBranch)}}"> | ||||
| 									<div class="ui dropdown button button-ghost gt-p-3" data-tooltip-content="{{$.locale.Tr "repo.branch.download" ($.DefaultBranch)}}"> | ||||
| 										{{svg "octicon-download"}} | ||||
| 										<div class="menu"> | ||||
| 											<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.DefaultBranch}}.zip" rel="nofollow">{{svg "octicon-file-zip"}} ZIP</a> | ||||
| @@ -51,7 +51,7 @@ | ||||
| 									</div> | ||||
| 								{{end}} | ||||
| 								{{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted) (not $.IsMirror)}} | ||||
| 									<button class="ui button button-ghost show-modal show-rename-branch-modal gt-mx-3" | ||||
| 									<button class="ui button button-ghost gt-p-3 show-modal show-rename-branch-modal" | ||||
| 										data-is-default-branch="true" | ||||
| 										data-modal="#rename-branch-modal" | ||||
| 										data-old-branch-name="{{$.DefaultBranch}}" | ||||
| @@ -134,7 +134,7 @@ | ||||
| 									</td> | ||||
| 									<td class="three wide right aligned overflow-visible"> | ||||
| 										{{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted)}} | ||||
| 											<button class="ui button button-ghost show-modal show-create-branch-modal gt-mx-3" | ||||
| 											<button class="ui button button-ghost gt-p-3 show-modal show-create-branch-modal" | ||||
| 												data-branch-from="{{.Name}}" | ||||
| 												data-branch-from-urlcomponent="{{PathEscapeSegments .Name}}" | ||||
| 												data-tooltip-content="{{$.locale.Tr "repo.branch.new_branch_from" .Name}}" | ||||
| @@ -144,12 +144,12 @@ | ||||
| 											</button> | ||||
| 										{{end}} | ||||
| 										{{if $.EnableFeed}} | ||||
| 											<a role="button" class="ui button button-ghost gt-mx-3" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .Name}}"> | ||||
| 											<a role="button" class="ui button button-ghost gt-p-3" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .Name}}"> | ||||
| 												{{svg "octicon-rss"}} | ||||
| 											</a> | ||||
| 										{{end}} | ||||
| 										{{if and (not .IsDeleted) (not $.DisableDownloadSourceArchives)}} | ||||
| 											<div class="ui dropdown button button-ghost gt-mx-3" data-tooltip-content="{{$.locale.Tr "repo.branch.download" (.Name)}}"> | ||||
| 											<div class="ui dropdown button button-ghost gt-p-3" data-tooltip-content="{{$.locale.Tr "repo.branch.download" (.Name)}}"> | ||||
| 												{{svg "octicon-download"}} | ||||
| 												<div class="menu"> | ||||
| 													<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments .Name}}.zip" rel="nofollow">{{svg "octicon-file-zip"}} ZIP</a> | ||||
| @@ -158,7 +158,7 @@ | ||||
| 											</div> | ||||
| 										{{end}} | ||||
| 										{{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted) (not $.IsMirror)}} | ||||
| 											<button class="ui button button-ghost show-modal show-rename-branch-modal gt-mx-3" | ||||
| 											<button class="ui button button-ghost gt-p-3 show-modal show-rename-branch-modal" | ||||
| 												data-is-default-branch="false" | ||||
| 												data-old-branch-name="{{.Name}}" | ||||
| 												data-modal="#rename-branch-modal" | ||||
| @@ -169,13 +169,13 @@ | ||||
| 										{{end}} | ||||
| 										{{if and $.IsWriter (not $.IsMirror) (not $.Repository.IsArchived) (not .IsProtected)}} | ||||
| 											{{if .IsDeleted}} | ||||
| 												<button class="ui button button-ghost undo-button gt-mx-3" data-url="{{$.Link}}/restore?branch_id={{.DeletedBranch.ID}}&name={{.DeletedBranch.Name}}&page={{$.Page.Paginater.Current}}" data-tooltip-content="{{$.locale.Tr "repo.branch.restore" (.Name)}}"> | ||||
| 												<button class="ui button button-ghost gt-p-3 undo-button" data-url="{{$.Link}}/restore?branch_id={{.DeletedBranch.ID}}&name={{.DeletedBranch.Name}}&page={{$.Page.Paginater.Current}}" data-tooltip-content="{{$.locale.Tr "repo.branch.restore" (.Name)}}"> | ||||
| 													<span class="text blue"> | ||||
| 														{{svg "octicon-reply"}} | ||||
| 													</span> | ||||
| 												</button> | ||||
| 											{{else}} | ||||
| 												<button class="ui button button-ghost delete-button delete-branch-button gt-mx-3" data-url="{{$.Link}}/delete?name={{.Name}}&page={{$.Page.Paginater.Current}}" data-tooltip-content="{{$.locale.Tr "repo.branch.delete" (.Name)}}" data-name="{{.Name}}"> | ||||
| 												<button class="ui button button-ghost gt-p-3 delete-button delete-branch-button" data-url="{{$.Link}}/delete?name={{.Name}}&page={{$.Page.Paginater.Current}}" data-tooltip-content="{{$.locale.Tr "repo.branch.delete" (.Name)}}" data-name="{{.Name}}"> | ||||
| 													{{svg "octicon-trash"}} | ||||
| 												</button> | ||||
| 											{{end}} | ||||
|   | ||||
| @@ -69,7 +69,7 @@ | ||||
| 										{{$subJumpablePathName}} | ||||
| 									{{else}} | ||||
| 										{{$subJumpablePathPrefixes := slice $subJumpablePathFields 0 $subJumpablePathFieldLast}} | ||||
| 										<span class="color-text-light-2">{{StringUtils.Join $subJumpablePathPrefixes "/"}}</span>/{{index $subJumpablePathFields $subJumpablePathFieldLast}} | ||||
| 										<span class="text light-2">{{StringUtils.Join $subJumpablePathPrefixes "/"}}</span>/{{index $subJumpablePathFields $subJumpablePathFieldLast}} | ||||
| 									{{end}} | ||||
| 								</a> | ||||
| 							{{else}} | ||||
|   | ||||
							
								
								
									
										25
									
								
								templates/shared/issueicon.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								templates/shared/issueicon.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| {{if .IsPull}} | ||||
| 	{{if and .PullRequest .PullRequest.HasMerged}} | ||||
| 		{{svg "octicon-git-merge" 16 "text purple"}} | ||||
| 	{{else if and .GetPullRequest .GetPullRequest.HasMerged}} | ||||
| 		{{svg "octicon-git-merge" 16 "text purple"}} | ||||
| 	{{else}} | ||||
| 		{{if .IsClosed}} | ||||
| 			{{svg "octicon-git-pull-request" 16 "text red"}} | ||||
| 		{{else}} | ||||
| 			{{if and .PullRequest .PullRequest.IsWorkInProgress}} | ||||
| 				{{svg "octicon-git-pull-request-draft" 16 "text grey"}} | ||||
| 			{{else if and .GetPullRequest .GetPullRequest.IsWorkInProgress}} | ||||
| 				{{svg "octicon-git-pull-request-draft" 16 "text grey"}} | ||||
| 			{{else}} | ||||
| 				{{svg "octicon-git-pull-request" 16 "text green"}} | ||||
| 			{{end}} | ||||
| 		{{end}} | ||||
| 	{{end}} | ||||
| {{else}} | ||||
| 	{{if .IsClosed}} | ||||
| 		{{svg "octicon-issue-closed" 16 "text red"}} | ||||
| 	{{else}} | ||||
| 		{{svg "octicon-issue-opened" 16 "text green"}} | ||||
| 	{{end}} | ||||
| {{end}} | ||||
| @@ -7,27 +7,7 @@ | ||||
| 					<input type="checkbox" autocomplete="off" class="issue-checkbox gt-mt-2 gt-mr-4" data-issue-id={{.ID}} aria-label="{{$.locale.Tr "repo.issues.action_check"}} "{{.Title}}""> | ||||
| 				{{end}} | ||||
| 				<div class="issue-item-icon"> | ||||
| 					{{if .IsPull}} | ||||
| 						{{if .PullRequest.HasMerged}} | ||||
| 							{{svg "octicon-git-merge" 16 "text purple"}} | ||||
| 						{{else}} | ||||
| 							{{if .IsClosed}} | ||||
| 								{{svg "octicon-git-pull-request" 16 "text red"}} | ||||
| 							{{else}} | ||||
| 								{{if .PullRequest.IsWorkInProgress}} | ||||
| 									{{svg "octicon-git-pull-request-draft" 16 "text grey"}} | ||||
| 								{{else}} | ||||
| 									{{svg "octicon-git-pull-request" 16 "text green"}} | ||||
| 								{{end}} | ||||
| 							{{end}} | ||||
| 						{{end}} | ||||
| 					{{else}} | ||||
| 						{{if .IsClosed}} | ||||
| 							{{svg "octicon-issue-closed" 16 "text red"}} | ||||
| 						{{else}} | ||||
| 							{{svg "octicon-issue-opened" 16 "text green"}} | ||||
| 						{{end}} | ||||
| 					{{end}} | ||||
| 					{{template "shared/issueicon" .}} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div class="issue-item-main gt-f1 gt-fc gt-df"> | ||||
|   | ||||
| @@ -1,20 +1,18 @@ | ||||
| <div role="main" aria-label="{{.Title}}" class="page-content user notification" id="notification_div" data-params="{{.Page.GetParams}}" data-sequence-number="{{.SequenceNumber}}"> | ||||
| 	<div class="ui container"> | ||||
| 		<h1 class="ui header gt-df gt-ac"> | ||||
| 			{{svg "octicon-bell" 28 "gt-mr-3 gt-mt-1"}} | ||||
| 			{{.locale.Tr "notification.notifications"}} | ||||
| 		</h1> | ||||
| 		<div class="ui top attached tabular menu"> | ||||
| 			{{$notificationUnreadCount := call .NotificationUnreadCount}} | ||||
| 			<a href="{{AppSubUrl}}/notifications?q=unread" class="{{if eq .Status 1}}active {{end}}item"> | ||||
| 				{{.locale.Tr "notification.unread"}} | ||||
| 				<div class="ui label {{if not $notificationUnreadCount}}gt-hidden{{end}}">{{$notificationUnreadCount}}</div> | ||||
| 			</a> | ||||
| 			<a href="{{AppSubUrl}}/notifications?q=read" class="{{if eq .Status 2}}active {{end}}item"> | ||||
| 				{{.locale.Tr "notification.read"}} | ||||
| 			</a> | ||||
| 		{{$notificationUnreadCount := call .NotificationUnreadCount}} | ||||
| 		<div class="gt-df gt-ac gt-sb gt-mb-4"> | ||||
| 			<div class="small-menu-items ui compact tiny menu"> | ||||
| 				<a class="{{if eq .Status 1}}active {{end}}item" href="{{AppSubUrl}}/notifications?q=unread"> | ||||
| 					{{.locale.Tr "notification.unread"}} | ||||
| 					<div class="notifications-unread-count ui label {{if not $notificationUnreadCount}}gt-hidden{{end}}">{{$notificationUnreadCount}}</div> | ||||
| 				</a> | ||||
| 				<a class="{{if eq .Status 2}}active {{end}}item" href="{{AppSubUrl}}/notifications?q=read"> | ||||
| 					{{.locale.Tr "notification.read"}} | ||||
| 				</a> | ||||
| 			</div> | ||||
| 			{{if and (eq .Status 1)}} | ||||
| 				<form class="gt-ml-auto" action="{{AppSubUrl}}/notifications/purge" method="POST"> | ||||
| 				<form action="{{AppSubUrl}}/notifications/purge" method="POST"> | ||||
| 					{{$.CsrfTokenHtml}} | ||||
| 					<div class="{{if not $notificationUnreadCount}}gt-hidden{{end}}"> | ||||
| 						<button class="ui mini button primary gt-mr-0" title='{{$.locale.Tr "notification.mark_all_as_read"}}'> | ||||
| @@ -24,113 +22,100 @@ | ||||
| 				</form> | ||||
| 			{{end}} | ||||
| 		</div> | ||||
| 		<div class="ui bottom attached active tab segment gt-p-3"> | ||||
| 			{{if eq (len .Notifications) 0}} | ||||
| 				<div class="gt-df gt-ac gt-fc gt-p-4"> | ||||
| 					{{svg "octicon-inbox" 56 "gt-mb-4"}} | ||||
| 					{{if eq .Status 1}} | ||||
| 						{{.locale.Tr "notification.no_unread"}} | ||||
| 					{{else}} | ||||
| 						{{.locale.Tr "notification.no_read"}} | ||||
| 					{{end}} | ||||
| 				</div> | ||||
| 			{{else}} | ||||
| 				<table class="ui unstackable very compact small table" id="notification_table"> | ||||
| 					<tbody> | ||||
| 						{{range $notification := .Notifications}} | ||||
| 							{{$issue := .Issue}} | ||||
| 							{{$repo := .Repository}} | ||||
| 							<tr id="notification_{{.ID}}"> | ||||
| 								<td class="collapsing gt-pl-4"> | ||||
| 									{{if eq .Status 3}} | ||||
| 										{{svg "octicon-pin" 16 "text blue"}} | ||||
| 									{{else if not $issue}} | ||||
| 										{{svg "octicon-repo" 16 "text grey"}} | ||||
| 									{{else if $issue.IsPull}} | ||||
| 										{{if $issue.IsClosed}} | ||||
| 											{{if $issue.GetPullRequest.HasMerged}} | ||||
| 												{{svg "octicon-git-merge" 16 "text purple"}} | ||||
| 											{{else}} | ||||
| 												{{svg "octicon-git-pull-request" 16 "text red"}} | ||||
| 											{{end}} | ||||
| 										{{else}} | ||||
| 											{{svg "octicon-git-pull-request" 16 "text green"}} | ||||
| 										{{end}} | ||||
| 									{{else}} | ||||
| 										{{if $issue.IsClosed}} | ||||
| 											{{svg "octicon-issue-closed" 16 "text red"}} | ||||
| 										{{else}} | ||||
| 											{{svg "octicon-issue-opened" 16 "text green"}} | ||||
| 										{{end}} | ||||
| 									{{end}} | ||||
| 								</td> | ||||
| 								<td class="eleven wide"> | ||||
| 									<a class="item issue-title muted" href="{{.Link}}"> | ||||
| 										{{if $issue}} | ||||
| 											#{{$issue.Index}} - {{$issue.Title | RenderEmoji $.Context | RenderCodeBlock}} | ||||
| 										{{else}} | ||||
| 											{{$repo.FullName}} | ||||
| 										{{end}} | ||||
| 									</a> | ||||
| 								</td> | ||||
| 								<td> | ||||
| 									<a class="item muted" href="{{$repo.Link}}">{{$repo.FullName}}</a> | ||||
| 								</td> | ||||
| 								<td class="collapsing"> | ||||
| 									{{if ne .Status 3}} | ||||
| 										<form action="{{AppSubUrl}}/notifications/status" method="POST"> | ||||
| 											{{$.CsrfTokenHtml}} | ||||
| 											<input type="hidden" name="notification_id" value="{{.ID}}"> | ||||
| 											<input type="hidden" name="status" value="pinned"> | ||||
| 											<button class="ui mini button button-ghost" title='{{$.locale.Tr "notification.pin"}}' | ||||
| 												data-url="{{AppSubUrl}}/notifications/status" | ||||
| 												data-status="pinned" | ||||
| 												data-page="{{$.Page.Paginater.Current}}" | ||||
| 												data-notification-id="{{.ID}}" | ||||
| 												data-q="{{$.Keyword}}"> | ||||
| 												{{svg "octicon-pin"}} | ||||
| 											</button> | ||||
| 										</form> | ||||
| 									{{end}} | ||||
| 								</td> | ||||
| 								<td class="collapsing"> | ||||
| 									{{if or (eq .Status 1) (eq .Status 3)}} | ||||
| 										<form action="{{AppSubUrl}}/notifications/status" method="POST"> | ||||
| 											{{$.CsrfTokenHtml}} | ||||
| 											<input type="hidden" name="notification_id" value="{{.ID}}"> | ||||
| 											<input type="hidden" name="status" value="read"> | ||||
| 											<input type="hidden" name="page" value="{{$.Page.Paginater.Current}}"> | ||||
| 											<button class="ui mini button button-ghost" title='{{$.locale.Tr "notification.mark_as_read"}}' | ||||
| 												data-url="{{AppSubUrl}}/notifications/status" | ||||
| 												data-status="read" | ||||
| 												data-page="{{$.Page.Paginater.Current}}" | ||||
| 												data-notification-id="{{.ID}}" | ||||
| 												data-q="{{$.Keyword}}"> | ||||
| 												{{svg "octicon-check"}} | ||||
| 											</button> | ||||
| 										</form> | ||||
| 									{{else if eq .Status 2}} | ||||
| 										<form action="{{AppSubUrl}}/notifications/status" method="POST"> | ||||
| 											{{$.CsrfTokenHtml}} | ||||
| 											<input type="hidden" name="notification_id" value="{{.ID}}"> | ||||
| 											<input type="hidden" name="status" value="unread"> | ||||
| 											<input type="hidden" name="page" value="{{$.Page.Paginater.Current}}"> | ||||
| 											<button class="ui mini button button-ghost" title='{{$.locale.Tr "notification.mark_as_unread"}}' | ||||
| 												data-url="{{AppSubUrl}}/notifications/status" | ||||
| 												data-status="unread" | ||||
| 												data-page="{{$.Page.Paginater.Current}}" | ||||
| 												data-notification-id="{{.ID}}" | ||||
| 												data-q="{{$.Keyword}}"> | ||||
| 												{{svg "octicon-bell"}} | ||||
| 											</button> | ||||
| 										</form> | ||||
| 									{{end}} | ||||
| 								</td> | ||||
| 							</tr> | ||||
| 		<div class="gt-p-0"> | ||||
| 			<div id="notification_table"> | ||||
| 				{{if eq (len .Notifications) 0}} | ||||
| 					<div class="gt-df gt-ac gt-fc gt-p-4"> | ||||
| 						{{svg "octicon-inbox" 56 "gt-mb-4"}} | ||||
| 						{{if eq .Status 1}} | ||||
| 							{{.locale.Tr "notification.no_unread"}} | ||||
| 						{{else}} | ||||
| 							{{.locale.Tr "notification.no_read"}} | ||||
| 						{{end}} | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			{{end}} | ||||
| 					</div> | ||||
| 				{{else}} | ||||
| 					{{$locale := .locale}} | ||||
| 					{{range $notification := .Notifications}} | ||||
| 						<div class="notifications-item gt-df gt-ac gt-fw gt-gap-3 gt-p-3" id="notification_{{.ID}}" data-status="{{.Status}}"> | ||||
| 							<div class="notifications-icon gt-ml-3 gt-mr-2 gt-self-start gt-mt-2"> | ||||
| 								{{if .Issue}} | ||||
| 									{{template "shared/issueicon" .Issue}} | ||||
| 								{{else}} | ||||
| 									{{svg "octicon-repo" 16 "text grey"}} | ||||
| 								{{end}} | ||||
| 							</div> | ||||
| 							<a class="notifications-link gt-df gt-f1 gt-fc silenced" href="{{.Link}}"> | ||||
| 								<div class="notifications-top-row gt-font-13"> | ||||
| 									{{.Repository.FullName}} <span class="text light-3">#{{.Issue.Index}}</span> | ||||
| 									{{if eq .Status 3}} | ||||
| 										{{svg "octicon-pin" 13 "text blue gt-mt-1 gt-ml-2"}} | ||||
| 									{{end}} | ||||
| 								</div> | ||||
| 								<div class="notifications-bottom-row gt-font-16 gt-py-1"> | ||||
| 									<span class="issue-title"> | ||||
| 										{{if .Issue}} | ||||
| 											{{.Issue.Title | RenderEmoji $.Context | RenderCodeBlock}} | ||||
| 										{{else}} | ||||
| 											{{.Repository.FullName}} | ||||
| 										{{end}} | ||||
| 									</span> | ||||
| 								</div> | ||||
| 							</a> | ||||
| 							<div class="notifications-updated gt-ac gt-mr-3"> | ||||
| 								{{TimeSinceUnix .Issue.UpdatedUnix $locale}} | ||||
| 							</div> | ||||
| 							<div class="notifications-buttons gt-ac gt-je gt-gap-2 gt-px-2"> | ||||
| 								{{if ne .Status 3}} | ||||
| 									<form action="{{AppSubUrl}}/notifications/status" method="POST"> | ||||
| 										{{$.CsrfTokenHtml}} | ||||
| 										<input type="hidden" name="notification_id" value="{{.ID}}"> | ||||
| 										<input type="hidden" name="status" value="pinned"> | ||||
| 										<button class="ui mini button button-ghost gt-p-3" title='{{$.locale.Tr "notification.pin"}}' | ||||
| 											data-url="{{AppSubUrl}}/notifications/status" | ||||
| 											data-status="pinned" | ||||
| 											data-page="{{$.Page.Paginater.Current}}" | ||||
| 											data-notification-id="{{.ID}}" | ||||
| 											data-q="{{$.Keyword}}"> | ||||
| 											{{svg "octicon-pin"}} | ||||
| 										</button> | ||||
| 									</form> | ||||
| 								{{end}} | ||||
| 								{{if or (eq .Status 1) (eq .Status 3)}} | ||||
| 									<form action="{{AppSubUrl}}/notifications/status" method="POST"> | ||||
| 										{{$.CsrfTokenHtml}} | ||||
| 										<input type="hidden" name="notification_id" value="{{.ID}}"> | ||||
| 										<input type="hidden" name="status" value="read"> | ||||
| 										<input type="hidden" name="page" value="{{$.Page.Paginater.Current}}"> | ||||
| 										<button class="ui mini button button-ghost gt-p-3" title='{{$.locale.Tr "notification.mark_as_read"}}' | ||||
| 											data-url="{{AppSubUrl}}/notifications/status" | ||||
| 											data-status="read" | ||||
| 											data-page="{{$.Page.Paginater.Current}}" | ||||
| 											data-notification-id="{{.ID}}" | ||||
| 											data-q="{{$.Keyword}}"> | ||||
| 											{{svg "octicon-check"}} | ||||
| 										</button> | ||||
| 									</form> | ||||
| 								{{else if eq .Status 2}} | ||||
| 									<form action="{{AppSubUrl}}/notifications/status" method="POST"> | ||||
| 										{{$.CsrfTokenHtml}} | ||||
| 										<input type="hidden" name="notification_id" value="{{.ID}}"> | ||||
| 										<input type="hidden" name="status" value="unread"> | ||||
| 										<input type="hidden" name="page" value="{{$.Page.Paginater.Current}}"> | ||||
| 										<button class="ui mini button button-ghost gt-p-3" title='{{$.locale.Tr "notification.mark_as_unread"}}' | ||||
| 											data-url="{{AppSubUrl}}/notifications/status" | ||||
| 											data-status="unread" | ||||
| 											data-page="{{$.Page.Paginater.Current}}" | ||||
| 											data-notification-id="{{.ID}}" | ||||
| 											data-q="{{$.Keyword}}"> | ||||
| 											{{svg "octicon-bell"}} | ||||
| 										</button> | ||||
| 									</form> | ||||
| 								{{end}} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					{{end}} | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		{{template "base/paginate" .}} | ||||
| 	</div> | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
|   --font-weight-normal: 400; | ||||
|   --font-weight-medium: 500; | ||||
|   --font-weight-semibold: 600; | ||||
|   --font-weight-bold: 700; | ||||
|   /* backgrounds */ | ||||
|   --checkbox-mask-checked: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 18 18" width="16" height="16"><path fill-rule="evenodd" d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"></path></svg>'); | ||||
|   --checkbox-mask-indeterminate: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2 7.75A.75.75 0 012.75 7h10a.75.75 0 010 1.5h-10A.75.75 0 012 7.75z"></path></svg>'); | ||||
| @@ -373,6 +374,7 @@ a.muted:hover [class*="color-text"], | ||||
|  | ||||
| a.silenced:hover { | ||||
|   color: inherit; | ||||
|   text-decoration: none; | ||||
| } | ||||
|  | ||||
| .delete-button, | ||||
| @@ -1417,6 +1419,18 @@ img.ui.avatar, | ||||
|   color: var(--color-text-light) !important; | ||||
| } | ||||
|  | ||||
| .text.light { | ||||
|   color: var(--color-text-light) !important; | ||||
| } | ||||
|  | ||||
| .text.light-2 { | ||||
|   color: var(--color-text-light-2) !important; | ||||
| } | ||||
|  | ||||
| .text.light-3 { | ||||
|   color: var(--color-text-light-3) !important; | ||||
| } | ||||
|  | ||||
| .text.light.grey { | ||||
|   color: var(--color-grey-light) !important; | ||||
| } | ||||
| @@ -2201,7 +2215,7 @@ a.ui.active.label:hover { | ||||
|   border-left: none; | ||||
| } | ||||
|  | ||||
| /* a ghost button can be used as inline text, it doesn't have obvious styles */ | ||||
| /* a ghost button is a button without border */ | ||||
| .button.button-ghost { | ||||
|   background: transparent; | ||||
|   border: none; | ||||
| @@ -2211,7 +2225,11 @@ a.ui.active.label:hover { | ||||
| } | ||||
|  | ||||
| .button.button-ghost:hover { | ||||
|   color: var(--color-primary); | ||||
|   background: var(--color-hover); | ||||
| } | ||||
|  | ||||
| .button.button-ghost:active { | ||||
|   background: var(--color-active); | ||||
| } | ||||
|  | ||||
| .two-toggle-buttons .button:not(.active):first-of-type { | ||||
| @@ -2538,8 +2556,8 @@ a.ui.basic.label:hover { | ||||
|   padding: 2.75px; | ||||
|   border-radius: 1em; | ||||
|   font-size: 11px; | ||||
|   font-weight: var(--font-weight-semibold); | ||||
|   line-height: .67em; | ||||
|   font-weight: var(--font-weight-bold); | ||||
|   line-height: .7; | ||||
| } | ||||
|  | ||||
| .rss-icon { | ||||
| @@ -2751,7 +2769,3 @@ table th[data-sortt-desc] .svg { | ||||
|   width: 15px; | ||||
|   height: 15px; | ||||
| } | ||||
|  | ||||
| .color-text-light-2 { | ||||
|   color: var(--color-text-light-2); | ||||
| } | ||||
|   | ||||
| @@ -73,6 +73,8 @@ Gitea's private styles use `g-` prefix. | ||||
| .gt-whitespace-pre-wrap { white-space: pre-wrap !important; } | ||||
| .gt-object-contain { object-fit: contain !important; } | ||||
| .gt-self-center { align-self: center !important; } | ||||
| .gt-self-start { align-self: flex-start !important; } | ||||
| .gt-self-end { align-self: flex-end !important; } | ||||
|  | ||||
| .gt-overflow-x-auto { overflow-x: auto !important; } | ||||
| .gt-overflow-x-scroll { overflow-x: scroll !important; } | ||||
| @@ -88,6 +90,7 @@ Gitea's private styles use `g-` prefix. | ||||
| .gt-font-normal { font-weight: var(--font-weight-normal) !important }; | ||||
| .gt-font-medium { font-weight: var(--font-weight-medium) !important }; | ||||
| .gt-font-semibold { font-weight: var(--font-weight-semibold) !important }; | ||||
| .gt-font-bold { font-weight: var(--font-weight-bold) !important }; | ||||
|  | ||||
| .gt-rounded { border-radius: var(--border-radius) !important; } | ||||
| .gt-rounded-top { border-radius: var(--border-radius) var(--border-radius) 0 0 !important; } | ||||
| @@ -249,6 +252,13 @@ Gitea's private styles use `g-` prefix. | ||||
|  | ||||
| .gt-shrink-0 { flex-shrink: 0 !important; } | ||||
|  | ||||
| .gt-font-13 { font-size: 13px !important } | ||||
| .gt-font-14 { font-size: 14px !important } | ||||
| .gt-font-15 { font-size: 15px !important } | ||||
| .gt-font-16 { font-size: 16px !important } | ||||
| .gt-font-17 { font-size: 17px !important } | ||||
| .gt-font-18 { font-size: 18px !important } | ||||
|  | ||||
| @media (max-width: 767px) { | ||||
|   .gt-db-small { display: block !important; } | ||||
|   .gt-w-100-small { width: 100% !important; } | ||||
|   | ||||
| @@ -121,18 +121,6 @@ | ||||
|   object-fit: contain; | ||||
| } | ||||
|  | ||||
| #notification_div .tab.segment { | ||||
|   overflow-x: auto; | ||||
| } | ||||
|  | ||||
| #notification_div .tabular.menu .active.item { | ||||
|   background: var(--color-box-body); | ||||
| } | ||||
|  | ||||
| #notification_table { | ||||
|   border: none; | ||||
| } | ||||
|  | ||||
| #readme_profile { | ||||
|   padding: 10px; | ||||
|   border-radius: 0.28571429rem; | ||||
| @@ -140,11 +128,29 @@ | ||||
|   border: 1px solid var(--color-secondary); | ||||
| } | ||||
|  | ||||
| #notification_table tr { | ||||
|   cursor: default; | ||||
| #notification_table { | ||||
|   background: var(--color-box-body); | ||||
|   border: 1px solid var(--color-secondary); | ||||
|   border-radius: var(--border-radius); | ||||
| } | ||||
|  | ||||
| #notification_table td a { | ||||
|   width: 100%; | ||||
|   display: inline-block; | ||||
| .notifications-item:hover { | ||||
|   background: var(--color-hover); | ||||
| } | ||||
|  | ||||
| .notifications-buttons { | ||||
|   display: none; | ||||
|   min-width: 74px; | ||||
| } | ||||
|  | ||||
| .notifications-updated { | ||||
|   display: flex; | ||||
| } | ||||
|  | ||||
| .notifications-item:hover .notifications-buttons { | ||||
|   display: flex; | ||||
| } | ||||
|  | ||||
| .notifications-item:hover .notifications-updated { | ||||
|   display: none; | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,30 @@ const {appSubUrl, csrfToken, notificationSettings, assetVersionEncoded} = window | ||||
| let notificationSequenceNumber = 0; | ||||
|  | ||||
| export function initNotificationsTable() { | ||||
|   const table = document.getElementById('notification_table'); | ||||
|   if (!table) return; | ||||
|  | ||||
|   // when page restores from bfcache, delete previously clicked items | ||||
|   window.addEventListener('pageshow', (e) => { | ||||
|     if (e.persisted) { // page was restored from bfcache | ||||
|       const table = document.getElementById('notification_table'); | ||||
|       const unreadCountEl = document.querySelector('.notifications-unread-count'); | ||||
|       let unreadCount = parseInt(unreadCountEl.textContent); | ||||
|       for (const item of table.querySelectorAll('.notifications-item[data-remove="true"]')) { | ||||
|         item.remove(); | ||||
|         unreadCount -= 1; | ||||
|       } | ||||
|       unreadCountEl.textContent = unreadCount; | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   // mark clicked unread links for deletion on bfcache restore | ||||
|   for (const link of table.querySelectorAll('.notifications-item[data-status="1"] .notifications-link')) { | ||||
|     link.addEventListener('click', (e) => { | ||||
|       e.target.closest('.notifications-item').setAttribute('data-remove', 'true'); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   $('#notification_table .button').on('click', function () { | ||||
|     (async () => { | ||||
|       const data = await updateNotification( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user