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