|
|
@ -103,13 +103,10 @@ |
|
|
|
showGivenToUser="true" |
|
|
|
/> |
|
|
|
|
|
|
|
<!-- Results List --> |
|
|
|
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4"> |
|
|
|
<h2 class="text-xl font-bold mb-4">Latest Activity</h2> |
|
|
|
<div :class="{ hidden: isHiddenSpinner }"> |
|
|
|
<p class="text-slate-500 text-center italic mt-4 mb-4"> |
|
|
|
<fa icon="spinner" class="fa-spin-pulse"></fa> Loading… |
|
|
|
</p> |
|
|
|
</div> |
|
|
|
<InfiniteScroll @reached-bottom="loadMoreGives"> |
|
|
|
<ul class="border-t border-slate-300"> |
|
|
|
<li |
|
|
|
class="border-b border-slate-300 py-2" |
|
|
@ -118,10 +115,11 @@ |
|
|
|
> |
|
|
|
<div |
|
|
|
class="border-b border-dashed border-slate-400 text-orange-400 pb-2 mb-2 font-bold uppercase text-sm" |
|
|
|
v-if="record.jwtId == feedLastViewedId" |
|
|
|
v-if="record.jwtId == feedLastViewedClaimId" |
|
|
|
> |
|
|
|
You've seen all the following |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="flex"> |
|
|
|
<fa icon="gift" class="pt-1 pr-2 text-slate-500"></fa> |
|
|
|
<span class="">{{ this.giveDescription(record) }}</span> |
|
|
@ -131,14 +129,26 @@ |
|
|
|
</div> |
|
|
|
</li> |
|
|
|
</ul> |
|
|
|
</InfiniteScroll> |
|
|
|
<div :class="{ hidden: isHiddenSpinner }"> |
|
|
|
<p class="text-slate-500 text-center italic mt-4 mb-4"> |
|
|
|
<fa icon="spinner" class="fa-spin-pulse"></fa> Loading… |
|
|
|
</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</section> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script lang="ts"> |
|
|
|
import { Component, Vue } from "vue-facing-decorator"; |
|
|
|
|
|
|
|
import EntityIcon from "@/components/EntityIcon.vue"; |
|
|
|
import GiftedDialog from "@/components/GiftedDialog.vue"; |
|
|
|
import InfiniteScroll from "@/components/InfiniteScroll.vue"; |
|
|
|
import QuickNav from "@/components/QuickNav.vue"; |
|
|
|
import { db, accountsDB } from "@/db/index"; |
|
|
|
import { Account } from "@/db/tables/accounts"; |
|
|
|
import { Contact } from "@/db/tables/contacts"; |
|
|
|
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings"; |
|
|
|
import { accessToken } from "@/libs/crypto"; |
|
|
|
import { |
|
|
@ -146,11 +156,7 @@ import { |
|
|
|
GiverInputInfo, |
|
|
|
GiveServerRecord, |
|
|
|
} from "@/libs/endorserServer"; |
|
|
|
import { Contact } from "@/db/tables/contacts"; |
|
|
|
import QuickNav from "@/components/QuickNav.vue"; |
|
|
|
import EntityIcon from "@/components/EntityIcon.vue"; |
|
|
|
import { IIdentifier } from "@veramo/core"; |
|
|
|
import { Account } from "@/db/tables/accounts"; |
|
|
|
|
|
|
|
interface Notification { |
|
|
|
group: string; |
|
|
@ -160,7 +166,7 @@ interface Notification { |
|
|
|
} |
|
|
|
|
|
|
|
@Component({ |
|
|
|
components: { GiftedDialog, QuickNav, EntityIcon }, |
|
|
|
components: { GiftedDialog, QuickNav, EntityIcon, InfiniteScroll }, |
|
|
|
}) |
|
|
|
export default class HomeView extends Vue { |
|
|
|
$notify!: (notification: Notification, timeout?: number) => void; |
|
|
@ -169,10 +175,9 @@ export default class HomeView extends Vue { |
|
|
|
allContacts: Array<Contact> = []; |
|
|
|
allMyDids: Array<string> = []; |
|
|
|
apiServer = ""; |
|
|
|
feedAllLoaded = false; |
|
|
|
feedData = []; |
|
|
|
feedPreviousOldestId?: string; |
|
|
|
feedLastViewedId?: string; |
|
|
|
feedLastViewedClaimId?: string; |
|
|
|
isHiddenSpinner = true; |
|
|
|
isRegistered = false; |
|
|
|
numAccounts = 0; |
|
|
@ -212,9 +217,12 @@ export default class HomeView extends Vue { |
|
|
|
this.apiServer = settings?.apiServer || ""; |
|
|
|
this.activeDid = settings?.activeDid || ""; |
|
|
|
this.allContacts = await db.contacts.toArray(); |
|
|
|
this.feedLastViewedId = settings?.lastViewedClaimId; |
|
|
|
this.feedLastViewedClaimId = settings?.lastViewedClaimId; |
|
|
|
this.isRegistered = !!settings?.isRegistered; |
|
|
|
|
|
|
|
// this returns a Promise but we don't need to wait for it |
|
|
|
this.updateAllFeed(); |
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any |
|
|
|
} catch (err: any) { |
|
|
|
this.$notify( |
|
|
@ -257,24 +265,33 @@ export default class HomeView extends Vue { |
|
|
|
return headers; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Data loader used by infinite scroller |
|
|
|
* @param payload is the flag from the InfiniteScroll indicating if it should load |
|
|
|
**/ |
|
|
|
public async loadMoreGives(payload: boolean) { |
|
|
|
if (payload) { |
|
|
|
this.updateAllFeed(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public async updateAllFeed() { |
|
|
|
this.isHiddenSpinner = false; |
|
|
|
await this.retrieveClaims(this.apiServer, this.feedPreviousOldestId) |
|
|
|
await this.retrieveGives(this.apiServer, this.feedPreviousOldestId) |
|
|
|
.then(async (results) => { |
|
|
|
if (results.data.length > 0) { |
|
|
|
this.feedData = this.feedData.concat(results.data); |
|
|
|
this.feedAllLoaded = results.hitLimit; |
|
|
|
this.feedPreviousOldestId = |
|
|
|
results.data[results.data.length - 1].jwtId; |
|
|
|
// The following update is only done on the first load. |
|
|
|
if ( |
|
|
|
this.feedLastViewedId == null || |
|
|
|
this.feedLastViewedId < results.data[0].jwtId |
|
|
|
this.feedLastViewedClaimId == null || |
|
|
|
this.feedLastViewedClaimId < results.data[0].jwtId |
|
|
|
) { |
|
|
|
await db.open(); |
|
|
|
db.settings.update(MASTER_SETTINGS_KEY, { |
|
|
|
lastViewedClaimId: results.data[0].jwtId, |
|
|
|
}); |
|
|
|
// but not for this page because we need to remember what it was before |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
@ -284,17 +301,22 @@ export default class HomeView extends Vue { |
|
|
|
{ |
|
|
|
group: "alert", |
|
|
|
type: "danger", |
|
|
|
title: "Export Error", |
|
|
|
title: "Feed Error", |
|
|
|
text: e.userMessage || "There was an error retrieving feed data.", |
|
|
|
}, |
|
|
|
-1, |
|
|
|
); |
|
|
|
}); |
|
|
|
|
|
|
|
this.isHiddenSpinner = true; |
|
|
|
} |
|
|
|
|
|
|
|
public async retrieveClaims(endorserApiServer: string, beforeId?: string) { |
|
|
|
/** |
|
|
|
* Retrieve claims in reverse chronological order |
|
|
|
* |
|
|
|
* @param beforeId the earliest ID (of previous searches) to search earlier |
|
|
|
* @return claims in reverse chronological order |
|
|
|
*/ |
|
|
|
public async retrieveGives(endorserApiServer: string, beforeId?: string) { |
|
|
|
const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId; |
|
|
|
const response = await fetch( |
|
|
|
endorserApiServer + "/api/v2/report/gives?" + beforeQuery, |
|
|
|