show number of favs/boosts and favs/boosts page
This commit is contained in:
		
							parent
							
								
									e7fc226935
								
							
						
					
					
						commit
						de34efc554
					
				
					 8 changed files with 245 additions and 47 deletions
				
			
		
							
								
								
									
										19
									
								
								routes/_api/reblogsAndFavs.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								routes/_api/reblogsAndFavs.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| import { get, paramsString } from '../_utils/ajax' | ||||
| 
 | ||||
| // TODO: paginate
 | ||||
| 
 | ||||
| export async function getReblogs(instanceName, accessToken, statusId, limit = 80) { | ||||
|   let url = `https://${instanceName}/api/v1/statuses/${statusId}/reblogged_by` | ||||
|   url += '?' + paramsString({ limit }) | ||||
|   return get(url, { | ||||
|     'Authorization': `Bearer ${accessToken}` | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
| export async function getFavorites(instanceName, accessToken, statusId, limit = 80) { | ||||
|   let url = `https://${instanceName}/api/v1/statuses/${statusId}/favourited_by` | ||||
|   url += '?' + paramsString({ limit }) | ||||
|   return get(url, { | ||||
|     'Authorization': `Bearer ${accessToken}` | ||||
|   }) | ||||
| } | ||||
							
								
								
									
										62
									
								
								routes/_components/AccountsListPage.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								routes/_components/AccountsListPage.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| <div class="accounts-page"> | ||||
|   {{#if loading}} | ||||
|     <LoadingPage /> | ||||
|   {{elseif accounts && accounts.length}} | ||||
|     <ul class="accounts-results"> | ||||
|       {{#each accounts as account}} | ||||
|         <AccountSearchResult :account /> | ||||
|       {{/each}} | ||||
|     </ul> | ||||
|   {{/if}} | ||||
| </div> | ||||
| <style> | ||||
|   .accounts-page { | ||||
|     min-height: 60vh; | ||||
|     padding: 20px 20px; | ||||
|   } | ||||
|   .accounts-results { | ||||
|     list-style: none; | ||||
|     box-sizing: border-box; | ||||
|     border: 1px solid var(--main-border); | ||||
|     border-radius: 2px; | ||||
|   } | ||||
|   @media (max-width: 767px) { | ||||
|     .accounts-page { | ||||
|       padding: 20px 10px; | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| <script> | ||||
|   import Layout from '../_components/Layout.html' | ||||
|   import { store } from '../_store/store' | ||||
|   import LoadingPage from '../_components/LoadingPage.html' | ||||
|   import AccountSearchResult from '../_components/search/AccountSearchResult.html' | ||||
|   import { toast } from '../_utils/toast' | ||||
| 
 | ||||
|   export default { | ||||
|     async oncreate() { | ||||
|       let accountsFetcher = this.get('accountsFetcher') | ||||
|       let statusId = this.get('statusId') | ||||
|       let instanceName = this.store.get('currentInstance') | ||||
|       let accessToken = this.store.get('accessToken') | ||||
|       try { | ||||
|         let accounts = await accountsFetcher(instanceName, accessToken, statusId) | ||||
|         this.set({ accounts: accounts }) | ||||
|       } catch (e) { | ||||
|         toast.say('Error: ' + (e.name || '') + ' ' + (e.message || '')) | ||||
|       } finally { | ||||
|         this.set({loading: false}) | ||||
|       } | ||||
|     }, | ||||
|     data: () => ({ | ||||
|       loading: true, | ||||
|       accounts: [] | ||||
|     }), | ||||
|     store: () => store, | ||||
|     components: { | ||||
|       Layout, | ||||
|       LoadingPage, | ||||
|       AccountSearchResult | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | @ -26,7 +26,7 @@ | |||
|     <StatusMediaAttachments status="{{originalStatus}}" :contextualStatusId on:recalculateHeight /> | ||||
|   {{/if}} | ||||
|   {{#if isStatusInOwnThread}} | ||||
|   <StatusAbsoluteDate status="{{originalStatus}}" /> | ||||
|   <StatusDetails status="{{originalStatus}}" /> | ||||
|   {{/if}} | ||||
|   <StatusToolbar :status :isStatusInOwnThread /> | ||||
| </article> | ||||
|  | @ -65,7 +65,7 @@ | |||
|       "spoiler-btn spoiler-btn" | ||||
|       "content     content" | ||||
|       "media       media" | ||||
|       "date        date" | ||||
|       "details     details" | ||||
|       "toolbar     toolbar"; | ||||
|     grid-template-columns: min-content 1fr; | ||||
|   } | ||||
|  | @ -83,7 +83,7 @@ | |||
|   import StatusAuthorName from './StatusAuthorName.html' | ||||
|   import StatusAuthorHandle from './StatusAuthorHandle.html' | ||||
|   import StatusRelativeDate from './StatusRelativeDate.html' | ||||
|   import StatusAbsoluteDate from './StatusAbsoluteDate.html' | ||||
|   import StatusDetails from './StatusDetails.html' | ||||
|   import StatusToolbar from './StatusToolbar.html' | ||||
|   import StatusMediaAttachments from './StatusMediaAttachments.html' | ||||
|   import StatusContent from './StatusContent.html' | ||||
|  | @ -116,7 +116,7 @@ | |||
|       StatusAuthorName, | ||||
|       StatusAuthorHandle, | ||||
|       StatusRelativeDate, | ||||
|       StatusAbsoluteDate, | ||||
|       StatusDetails, | ||||
|       StatusToolbar, | ||||
|       StatusMediaAttachments, | ||||
|       StatusContent, | ||||
|  |  | |||
|  | @ -1,37 +0,0 @@ | |||
| <ExternalLink class="status-absolute-date" href="{{status.url}}" showIcon="true"> | ||||
|   <time datetime={{createdAtDate}} title="{{formattedDate}}">{{formattedDate}}</time> | ||||
| </ExternalLink> | ||||
| <style> | ||||
|   :global(.status-absolute-date) { | ||||
|     grid-area: date; | ||||
|     font-size: 1.1em; | ||||
|     white-space: nowrap; | ||||
|     margin: 0 5px 10px; | ||||
|     justify-self: right; | ||||
|   } | ||||
| 
 | ||||
|   :global(.status-absolute-date, .status-absolute-date:hover, .status-absolute-date:visited) { | ||||
|     color: var(--deemphasized-text-color); | ||||
|   } | ||||
| </style> | ||||
| <script> | ||||
|   import ExternalLink from '../ExternalLink.html' | ||||
| 
 | ||||
|   const formatter = new Intl.DateTimeFormat('en-US', { | ||||
|     year: 'numeric', | ||||
|     month: 'long', | ||||
|     day: 'numeric', | ||||
|     hour: '2-digit', | ||||
|     minute: '2-digit' | ||||
|   }) | ||||
| 
 | ||||
|   export default { | ||||
|     computed: { | ||||
|       createdAtDate: (status) => status.created_at, | ||||
|       formattedDate: (createdAtDate) => formatter.format(new Date(createdAtDate)) | ||||
|     }, | ||||
|     components: { | ||||
|       ExternalLink | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
							
								
								
									
										104
									
								
								routes/_components/status/StatusDetails.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								routes/_components/status/StatusDetails.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,104 @@ | |||
| <div class="status-details"> | ||||
|   <ExternalLink class="status-absolute-date" href="{{status.url}}" showIcon="true"> | ||||
|     <time datetime={{createdAtDate}} title="{{formattedDate}}">{{formattedDate}}</time> | ||||
|   </ExternalLink> | ||||
|   <a class="status-favs-reblogs" href="/statuses/{{statusId}}/reblogs"> | ||||
|     <svg> | ||||
|       <use xlink:href="#fa-retweet"/> | ||||
|     </svg> | ||||
|     <span>{{numReblogs}}</span> | ||||
|   </a> | ||||
|   <a class="status-favs-reblogs" href="/statuses/{{statusId}}/favorites"> | ||||
|     <svg> | ||||
|       <use xlink:href="#fa-star" /> | ||||
|     </svg> | ||||
|     <span>{{numFavs}}</span> | ||||
|   </a> | ||||
| </div> | ||||
| <style> | ||||
|   .status-details { | ||||
|     grid-area: details; | ||||
|     display: grid; | ||||
|     grid-template-columns: minmax(0, max-content) min-content min-content; | ||||
|     grid-gap: 20px; | ||||
|     align-items: center; | ||||
|     justify-content: left; | ||||
|     margin: 0 5px 10px; | ||||
|   } | ||||
|   :global(.status-absolute-date) { | ||||
|     font-size: 1.1em; | ||||
|     min-width: 0; | ||||
|   } | ||||
| 
 | ||||
|   :global(.status-absolute-date time) { | ||||
|     word-wrap: break-word; | ||||
|     overflow: hidden; | ||||
|     white-space: pre-wrap; | ||||
|   } | ||||
| 
 | ||||
|   .status-favs-reblogs { | ||||
|     font-size: 1.1em; | ||||
|     display: flex; | ||||
|     flex-direction: row; | ||||
|     align-items: center; | ||||
|   } | ||||
| 
 | ||||
|   .status-favs-reblogs span { | ||||
|     margin-left: 5px; | ||||
|   } | ||||
| 
 | ||||
|   .status-favs-reblogs, | ||||
|   .status-favs-reblogs:hover, | ||||
|   .status-favs-reblogs:visited { | ||||
|     color: var(--deemphasized-text-color); | ||||
|   } | ||||
| 
 | ||||
|   .status-favs-reblogs svg { | ||||
|     fill: var(--deemphasized-text-color); | ||||
|     width: 18px; | ||||
|     height: 18px; | ||||
|   } | ||||
| 
 | ||||
|   :global(.status-absolute-date, .status-absolute-date:hover, .status-absolute-date:visited) { | ||||
|     color: var(--deemphasized-text-color); | ||||
|   } | ||||
| 
 | ||||
|   @media (max-width: 479px) { | ||||
|     :global(.status-absolute-date) { | ||||
|       font-size: 1em; | ||||
|     } | ||||
|     .status-favs-reblogs { | ||||
|       font-size: 1em; | ||||
|     } | ||||
|     .status-details { | ||||
|       grid-gap: 5px; | ||||
|       justify-content: space-between; | ||||
|     } | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
| </style> | ||||
| <script> | ||||
|   import ExternalLink from '../ExternalLink.html' | ||||
| 
 | ||||
|   const formatter = new Intl.DateTimeFormat('en-US', { | ||||
|     year: 'numeric', | ||||
|     month: 'long', | ||||
|     day: 'numeric', | ||||
|     hour: '2-digit', | ||||
|     minute: '2-digit' | ||||
|   }) | ||||
| 
 | ||||
|   export default { | ||||
|     computed: { | ||||
|       statusId: (status) => status.id, | ||||
|       createdAtDate: (status) => status.created_at, | ||||
|       numReblogs: (status) => status.reblogs_count || 0, | ||||
|       numFavs: (status) => status.favourites_count || 0, | ||||
|       formattedDate: (createdAtDate) => formatter.format(new Date(createdAtDate)) | ||||
|     }, | ||||
|     components: { | ||||
|       ExternalLink | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
							
								
								
									
										25
									
								
								routes/statuses/[statusId]/favorites.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								routes/statuses/[statusId]/favorites.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| <:Head> | ||||
|   <title>Pinafore – Favorites</title> | ||||
| </:Head> | ||||
| 
 | ||||
| <Layout page='favorites'> | ||||
|   <AccountsListPage :accountsFetcher :statusId /> | ||||
| </Layout> | ||||
| <script> | ||||
|   import Layout from '../../_components/Layout.html' | ||||
|   import { getFavorites } from '../../_api/reblogsAndFavs' | ||||
|   import AccountsListPage from '../../_components/AccountsListPage.html' | ||||
| 
 | ||||
|   export default { | ||||
|     data: () => ({ | ||||
|       accountsFetcher: getFavorites | ||||
|     }), | ||||
|     computed: { | ||||
|       statusId: params => params.statusId | ||||
|     }, | ||||
|     components: { | ||||
|       Layout, | ||||
|       AccountsListPage | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | @ -17,12 +17,12 @@ | |||
|   {{/if}} | ||||
| </Layout> | ||||
| <script> | ||||
|   import Layout from '../_components/Layout.html' | ||||
|   import LazyTimeline from '../_components/timeline/LazyTimeline.html' | ||||
|   import FreeTextLayout from '../_components/FreeTextLayout.html' | ||||
|   import { store } from '../_store/store.js' | ||||
|   import HiddenFromSSR from '../_components/HiddenFromSSR' | ||||
|   import DynamicPageBanner from '../_components/DynamicPageBanner.html' | ||||
|   import Layout from '../../_components/Layout.html' | ||||
|   import LazyTimeline from '../../_components/timeline/LazyTimeline.html' | ||||
|   import FreeTextLayout from '../../_components/FreeTextLayout.html' | ||||
|   import { store } from '../../_store/store.js' | ||||
|   import HiddenFromSSR from '../../_components/HiddenFromSSR' | ||||
|   import DynamicPageBanner from '../../_components/DynamicPageBanner.html' | ||||
| 
 | ||||
|   export default { | ||||
|     store: () => store, | ||||
							
								
								
									
										25
									
								
								routes/statuses/[statusId]/reblogs.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								routes/statuses/[statusId]/reblogs.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| <:Head> | ||||
|   <title>Pinafore – Reblogs</title> | ||||
| </:Head> | ||||
| 
 | ||||
| <Layout page='reblogs'> | ||||
|   <AccountsListPage :accountsFetcher :statusId /> | ||||
| </Layout> | ||||
| <script> | ||||
|   import Layout from '../../_components/Layout.html' | ||||
|   import { getReblogs } from '../../_api/reblogsAndFavs' | ||||
|   import AccountsListPage from '../../_components/AccountsListPage.html' | ||||
| 
 | ||||
|   export default { | ||||
|     data: () => ({ | ||||
|       accountsFetcher: getReblogs | ||||
|     }), | ||||
|     computed: { | ||||
|       statusId: params => params.statusId | ||||
|     }, | ||||
|     components: { | ||||
|       Layout, | ||||
|       AccountsListPage | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
		Loading…
	
	Add table
		
		Reference in a new issue