docs: enhance component documentation with usage and reference tracking
- Add comprehensive JSDoc comments to HomeView and InfiniteScroll components - Document method visibility (@public/@internal) and usage contexts - Add clear references to where methods are called from (template, components, lifecycle) - Include file-level documentation with component descriptions - Document component dependencies and template usage - Add parameter and return type documentation - Clarify method call chains and dependencies - Document event emissions and component interactions This commit improves code maintainability by making method usage and component relationships more explicit in the documentation.
This commit is contained in:
@@ -1,3 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @file InfiniteScroll.vue
|
||||||
|
* @description A Vue component that implements infinite scrolling functionality using the Intersection Observer API.
|
||||||
|
* This component emits a 'reached-bottom' event when the user scrolls near the bottom of the content.
|
||||||
|
* It includes debouncing to prevent multiple rapid triggers and loading state management.
|
||||||
|
*
|
||||||
|
* @author Matthew Raymer
|
||||||
|
* @version 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="scrollContainer">
|
<div ref="scrollContainer">
|
||||||
<slot />
|
<slot />
|
||||||
@@ -8,15 +18,51 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Emit, Prop, Vue } from "vue-facing-decorator";
|
import { Component, Emit, Prop, Vue } from "vue-facing-decorator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InfiniteScroll Component
|
||||||
|
*
|
||||||
|
* This component implements infinite scrolling functionality by observing when a user
|
||||||
|
* scrolls near the bottom of the content. It uses the Intersection Observer API for
|
||||||
|
* efficient scroll detection and includes debouncing to prevent multiple rapid triggers.
|
||||||
|
*
|
||||||
|
* Usage in template:
|
||||||
|
* ```vue
|
||||||
|
* <InfiniteScroll @reached-bottom="loadMore">
|
||||||
|
* <div>Content goes here</div>
|
||||||
|
* </InfiniteScroll>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Props:
|
||||||
|
* - distance: number (default: 200) - Distance in pixels from the bottom at which to trigger the event
|
||||||
|
*
|
||||||
|
* Events:
|
||||||
|
* - reached-bottom: Emitted when the user scrolls near the bottom of the content
|
||||||
|
*/
|
||||||
@Component
|
@Component
|
||||||
export default class InfiniteScroll extends Vue {
|
export default class InfiniteScroll extends Vue {
|
||||||
|
/** Distance in pixels from the bottom at which to trigger the reached-bottom event */
|
||||||
@Prop({ default: 200 })
|
@Prop({ default: 200 })
|
||||||
readonly distance!: number;
|
readonly distance!: number;
|
||||||
|
|
||||||
|
/** Intersection Observer instance for detecting scroll position */
|
||||||
private observer!: IntersectionObserver;
|
private observer!: IntersectionObserver;
|
||||||
|
|
||||||
|
/** Flag to track initial render state */
|
||||||
private isInitialRender = true;
|
private isInitialRender = true;
|
||||||
|
|
||||||
|
/** Flag to prevent multiple simultaneous loading states */
|
||||||
private isLoading = false;
|
private isLoading = false;
|
||||||
|
|
||||||
|
/** Timeout ID for debouncing scroll events */
|
||||||
private debounceTimeout: number | null = null;
|
private debounceTimeout: number | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vue lifecycle hook that runs after component updates.
|
||||||
|
* Initializes the Intersection Observer if not already set up.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Used internally by Vue's lifecycle system
|
||||||
|
*/
|
||||||
updated() {
|
updated() {
|
||||||
if (!this.observer) {
|
if (!this.observer) {
|
||||||
const options = {
|
const options = {
|
||||||
@@ -32,7 +78,13 @@ export default class InfiniteScroll extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'beforeUnmount' hook runs before unmounting the component
|
/**
|
||||||
|
* Vue lifecycle hook that runs before component unmounting.
|
||||||
|
* Cleans up the Intersection Observer and any pending timeouts.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Used internally by Vue's lifecycle system
|
||||||
|
*/
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
if (this.observer) {
|
if (this.observer) {
|
||||||
this.observer.disconnect();
|
this.observer.disconnect();
|
||||||
@@ -42,6 +94,17 @@ export default class InfiniteScroll extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles intersection observer callbacks when the sentinel element becomes visible.
|
||||||
|
* Implements debouncing to prevent multiple rapid triggers and manages loading state.
|
||||||
|
*
|
||||||
|
* @param entries - Array of IntersectionObserverEntry objects
|
||||||
|
* @returns false (required by @Emit decorator)
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Used internally by the Intersection Observer
|
||||||
|
* @emits reached-bottom - Emitted when the user scrolls near the bottom
|
||||||
|
*/
|
||||||
@Emit("reached-bottom")
|
@Emit("reached-bottom")
|
||||||
handleIntersection(entries: IntersectionObserverEntry[]) {
|
handleIntersection(entries: IntersectionObserverEntry[]) {
|
||||||
const entry = entries[0];
|
const entry = entries[0];
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @file HomeView.vue
|
||||||
|
* @description Main view component for the application's home page. Handles user identity, feed management,
|
||||||
|
* and interaction with various dialogs and components. Implements infinite scrolling for activity feed
|
||||||
|
* and manages user registration status.
|
||||||
|
*
|
||||||
|
* @author Matthew Raymer
|
||||||
|
* @version 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Home" />
|
<QuickNav selected="Home" />
|
||||||
<TopMessage />
|
<TopMessage />
|
||||||
@@ -345,13 +355,30 @@ import { logger } from "../utils/logger";
|
|||||||
import { GiveRecordWithContactInfo } from "types";
|
import { GiveRecordWithContactInfo } from "types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HomeView - Main view component for the application's home page
|
* HomeView Component
|
||||||
*
|
*
|
||||||
* Workflow:
|
* Main view component that handles:
|
||||||
* 1. On mount, initializes user identity, settings, and data
|
* 1. User identity and registration management
|
||||||
* 2. Handles user registration status
|
* 2. Activity feed with infinite scrolling
|
||||||
* 3. Manages feed of activities and offers
|
* 3. Contact management and display
|
||||||
* 4. Provides interface for creating and viewing claims
|
* 4. Gift/claim creation and viewing
|
||||||
|
* 5. Feed filtering and settings
|
||||||
|
*
|
||||||
|
* Template Usage:
|
||||||
|
* ```vue
|
||||||
|
* <HomeView>
|
||||||
|
* <!-- Content is managed internally -->
|
||||||
|
* </HomeView>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Component Dependencies:
|
||||||
|
* - QuickNav: Navigation component
|
||||||
|
* - TopMessage: Message display component
|
||||||
|
* - OnboardingDialog: User onboarding flow
|
||||||
|
* - GiftedDialog: Gift creation interface
|
||||||
|
* - FeedFilters: Feed filtering options
|
||||||
|
* - InfiniteScroll: Infinite scrolling functionality
|
||||||
|
* - ActivityListItem: Individual activity display
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
@@ -417,6 +444,9 @@ export default class HomeView extends Vue {
|
|||||||
* 5. Load feed data
|
* 5. Load feed data
|
||||||
* 6. Load new offers
|
* 6. Load new offers
|
||||||
* 7. Check onboarding status
|
* 7. Check onboarding status
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called automatically by Vue lifecycle system
|
||||||
*/
|
*/
|
||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
@@ -436,6 +466,11 @@ export default class HomeView extends Vue {
|
|||||||
* Initializes user identity
|
* Initializes user identity
|
||||||
* - Retrieves existing DIDs
|
* - Retrieves existing DIDs
|
||||||
* - Creates new DID if none exists
|
* - Creates new DID if none exists
|
||||||
|
* - Loads user settings and contacts
|
||||||
|
* - Checks registration status
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted()
|
||||||
* @throws Logs error if DID retrieval fails
|
* @throws Logs error if DID retrieval fails
|
||||||
*/
|
*/
|
||||||
private async initializeIdentity() {
|
private async initializeIdentity() {
|
||||||
@@ -541,6 +576,9 @@ export default class HomeView extends Vue {
|
|||||||
* - Feed filters and view settings
|
* - Feed filters and view settings
|
||||||
* - Registration status
|
* - Registration status
|
||||||
* - Notification acknowledgments
|
* - Notification acknowledgments
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted() and reloadFeedOnChange()
|
||||||
*/
|
*/
|
||||||
private async loadSettings() {
|
private async loadSettings() {
|
||||||
const settings = await retrieveSettingsForActiveAccount();
|
const settings = await retrieveSettingsForActiveAccount();
|
||||||
@@ -562,6 +600,9 @@ export default class HomeView extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Loads user contacts from database
|
* Loads user contacts from database
|
||||||
* Used for displaying contact info in feed and actions
|
* Used for displaying contact info in feed and actions
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted() and initializeIdentity()
|
||||||
*/
|
*/
|
||||||
private async loadContacts() {
|
private async loadContacts() {
|
||||||
this.allContacts = await db.contacts.toArray();
|
this.allContacts = await db.contacts.toArray();
|
||||||
@@ -572,6 +613,9 @@ export default class HomeView extends Vue {
|
|||||||
* - Checks if unregistered user can access API
|
* - Checks if unregistered user can access API
|
||||||
* - Updates registration status if successful
|
* - Updates registration status if successful
|
||||||
* - Preserves unregistered state on failure
|
* - Preserves unregistered state on failure
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted() and initializeIdentity()
|
||||||
*/
|
*/
|
||||||
private async checkRegistrationStatus() {
|
private async checkRegistrationStatus() {
|
||||||
if (!this.isRegistered && this.activeDid) {
|
if (!this.isRegistered && this.activeDid) {
|
||||||
@@ -598,6 +642,9 @@ export default class HomeView extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Initializes feed data
|
* Initializes feed data
|
||||||
* Triggers updateAllFeed() to populate activity feed
|
* Triggers updateAllFeed() to populate activity feed
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted()
|
||||||
*/
|
*/
|
||||||
private async loadFeedData() {
|
private async loadFeedData() {
|
||||||
await this.updateAllFeed();
|
await this.updateAllFeed();
|
||||||
@@ -609,6 +656,9 @@ export default class HomeView extends Vue {
|
|||||||
* - Number of new direct offers
|
* - Number of new direct offers
|
||||||
* - Number of new project offers
|
* - Number of new project offers
|
||||||
* - Rate limit status for both
|
* - Rate limit status for both
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted() and initializeIdentity()
|
||||||
* @requires Active DID
|
* @requires Active DID
|
||||||
*/
|
*/
|
||||||
private async loadNewOffers() {
|
private async loadNewOffers() {
|
||||||
@@ -636,6 +686,9 @@ export default class HomeView extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Checks if user needs onboarding
|
* Checks if user needs onboarding
|
||||||
* Opens onboarding dialog if not completed
|
* Opens onboarding dialog if not completed
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted()
|
||||||
*/
|
*/
|
||||||
private async checkOnboarding() {
|
private async checkOnboarding() {
|
||||||
const settings = await retrieveSettingsForActiveAccount();
|
const settings = await retrieveSettingsForActiveAccount();
|
||||||
@@ -648,6 +701,9 @@ export default class HomeView extends Vue {
|
|||||||
* Handles errors during initialization
|
* Handles errors during initialization
|
||||||
* - Logs error to console and database
|
* - Logs error to console and database
|
||||||
* - Displays user notification
|
* - Displays user notification
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by mounted() and handleFeedError()
|
||||||
* @param err Error object with optional userMessage
|
* @param err Error object with optional userMessage
|
||||||
*/
|
*/
|
||||||
private handleError(err: unknown) {
|
private handleError(err: unknown) {
|
||||||
@@ -667,6 +723,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if feed results are being filtered
|
* Checks if feed results are being filtered
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Used in template for filter button display
|
||||||
* @returns true if visible or nearby filters are active
|
* @returns true if visible or nearby filters are active
|
||||||
*/
|
*/
|
||||||
resultsAreFiltered() {
|
resultsAreFiltered() {
|
||||||
@@ -675,6 +734,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if browser notifications are supported
|
* Checks if browser notifications are supported
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Used in template for notification feature detection
|
||||||
* @returns true if Notification API is available
|
* @returns true if Notification API is available
|
||||||
*/
|
*/
|
||||||
notificationsSupported() {
|
notificationsSupported() {
|
||||||
@@ -686,6 +748,9 @@ export default class HomeView extends Vue {
|
|||||||
* - Updates filter states
|
* - Updates filter states
|
||||||
* - Clears existing feed data
|
* - Clears existing feed data
|
||||||
* - Triggers new feed load
|
* - Triggers new feed load
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by FeedFilters component when filters change
|
||||||
*/
|
*/
|
||||||
async reloadFeedOnChange() {
|
async reloadFeedOnChange() {
|
||||||
const settings = await retrieveSettingsForActiveAccount();
|
const settings = await retrieveSettingsForActiveAccount();
|
||||||
@@ -700,6 +765,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads more feed items for infinite scroll
|
* Loads more feed items for infinite scroll
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by InfiniteScroll component when bottom is reached
|
||||||
* @param payload Boolean indicating if more items should be loaded
|
* @param payload Boolean indicating if more items should be loaded
|
||||||
*/
|
*/
|
||||||
async loadMoreGives(payload: boolean) {
|
async loadMoreGives(payload: boolean) {
|
||||||
@@ -711,6 +779,15 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if coordinates fall within any search box
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by shouldIncludeRecord() for location-based filtering
|
||||||
|
* @param lat Latitude to check
|
||||||
|
* @param long Longitude to check
|
||||||
|
* @returns true if coordinates are within any search box
|
||||||
|
*/
|
||||||
latLongInAnySearchBox(lat: number, long: number) {
|
latLongInAnySearchBox(lat: number, long: number) {
|
||||||
for (const boxInfo of this.searchBoxes) {
|
for (const boxInfo of this.searchBoxes) {
|
||||||
if (
|
if (
|
||||||
@@ -729,6 +806,9 @@ export default class HomeView extends Vue {
|
|||||||
* - Handles filtering of results
|
* - Handles filtering of results
|
||||||
* - Updates last viewed claim ID
|
* - Updates last viewed claim ID
|
||||||
* - Manages loading state
|
* - Manages loading state
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by loadMoreGives() and initializeIdentity()
|
||||||
*/
|
*/
|
||||||
async updateAllFeed() {
|
async updateAllFeed() {
|
||||||
this.isFeedLoading = true;
|
this.isFeedLoading = true;
|
||||||
@@ -754,6 +834,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes feed results and adds them to feedData
|
* Processes feed results and adds them to feedData
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by updateAllFeed()
|
||||||
*/
|
*/
|
||||||
private async processFeedResults(records: GiveSummaryRecord[]) {
|
private async processFeedResults(records: GiveSummaryRecord[]) {
|
||||||
for (const record of records) {
|
for (const record of records) {
|
||||||
@@ -767,6 +850,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a single record and returns it if it passes filters
|
* Processes a single record and returns it if it passes filters
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processFeedResults()
|
||||||
*/
|
*/
|
||||||
private async processRecord(record: GiveSummaryRecord): Promise<GiveRecordWithContactInfo | null> {
|
private async processRecord(record: GiveSummaryRecord): Promise<GiveRecordWithContactInfo | null> {
|
||||||
const claim = this.extractClaim(record);
|
const claim = this.extractClaim(record);
|
||||||
@@ -786,6 +872,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts claim from record, handling both direct and wrapped claims
|
* Extracts claim from record, handling both direct and wrapped claims
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private extractClaim(record: GiveSummaryRecord) {
|
private extractClaim(record: GiveSummaryRecord) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -794,6 +883,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts giver DID from claim
|
* Extracts giver DID from claim
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private extractGiverDid(claim: any) {
|
private extractGiverDid(claim: any) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -802,6 +894,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts recipient DID from claim
|
* Extracts recipient DID from claim
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private extractRecipientDid(claim: any) {
|
private extractRecipientDid(claim: any) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -810,6 +905,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets fulfills plan from cache
|
* Gets fulfills plan from cache
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private async getFulfillsPlan(record: GiveSummaryRecord) {
|
private async getFulfillsPlan(record: GiveSummaryRecord) {
|
||||||
return await getPlanFromCache(
|
return await getPlanFromCache(
|
||||||
@@ -822,6 +920,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if record should be included based on filters
|
* Checks if record should be included based on filters
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private shouldIncludeRecord(record: GiveSummaryRecord, fulfillsPlan: any): boolean {
|
private shouldIncludeRecord(record: GiveSummaryRecord, fulfillsPlan: any): boolean {
|
||||||
if (!this.isAnyFeedFilterOn) {
|
if (!this.isAnyFeedFilterOn) {
|
||||||
@@ -844,6 +945,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts provider from claim
|
* Extracts provider from claim
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private extractProvider(claim: any) {
|
private extractProvider(claim: any) {
|
||||||
return Array.isArray(claim.provider) ? claim.provider[0] : claim.provider;
|
return Array.isArray(claim.provider) ? claim.provider[0] : claim.provider;
|
||||||
@@ -851,6 +955,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets provided by plan from cache
|
* Gets provided by plan from cache
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private async getProvidedByPlan(provider: any) {
|
private async getProvidedByPlan(provider: any) {
|
||||||
return await getPlanFromCache(
|
return await getPlanFromCache(
|
||||||
@@ -863,6 +970,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a feed record with contact info
|
* Creates a feed record with contact info
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by processRecord()
|
||||||
*/
|
*/
|
||||||
private createFeedRecord(
|
private createFeedRecord(
|
||||||
record: GiveSummaryRecord,
|
record: GiveSummaryRecord,
|
||||||
@@ -908,6 +1018,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the last viewed claim ID in settings
|
* Updates the last viewed claim ID in settings
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by updateAllFeed()
|
||||||
*/
|
*/
|
||||||
private async updateFeedLastViewedId(records: GiveSummaryRecord[]) {
|
private async updateFeedLastViewedId(records: GiveSummaryRecord[]) {
|
||||||
if (
|
if (
|
||||||
@@ -923,6 +1036,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles feed error and shows notification
|
* Handles feed error and shows notification
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by updateAllFeed()
|
||||||
*/
|
*/
|
||||||
private handleFeedError(e: any) {
|
private handleFeedError(e: any) {
|
||||||
logger.error("Error with feed load:", e);
|
logger.error("Error with feed load:", e);
|
||||||
@@ -939,9 +1055,12 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve claims in reverse chronological order
|
* Retrieve claims in reverse chronological order
|
||||||
*
|
*
|
||||||
* @param beforeId the earliest ID (of previous searches) to search earlier
|
* @internal
|
||||||
* @return claims in reverse chronological order
|
* Called by updateAllFeed()
|
||||||
|
* @param endorserApiServer API server URL
|
||||||
|
* @param beforeId OptioCalled by updateAllFeed()nal ID to fetch earlier results
|
||||||
|
* @returns claims in reverse chronological order
|
||||||
*/
|
*/
|
||||||
async retrieveGives(endorserApiServer: string, beforeId?: string) {
|
async retrieveGives(endorserApiServer: string, beforeId?: string) {
|
||||||
const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId;
|
const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId;
|
||||||
@@ -974,6 +1093,14 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats gift description with giver and recipient info
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Used in template for displaying gift descriptions
|
||||||
|
* @param giveRecord Record containing gift information
|
||||||
|
* @returns formatted description string
|
||||||
|
*/
|
||||||
giveDescription(giveRecord: GiveRecordWithContactInfo) {
|
giveDescription(giveRecord: GiveRecordWithContactInfo) {
|
||||||
// similar code is in endorser-mobile utility.ts
|
// similar code is in endorser-mobile utility.ts
|
||||||
// claim.claim happen for some claims wrapped in a Verifiable Credential
|
// claim.claim happen for some claims wrapped in a Verifiable Credential
|
||||||
@@ -1054,10 +1181,23 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to activity page
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by template click handler
|
||||||
|
*/
|
||||||
goToActivityToUserPage() {
|
goToActivityToUserPage() {
|
||||||
this.$router.push({ name: "new-activity" });
|
this.$router.push({ name: "new-activity" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to claim details page
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by ActivityListItem component
|
||||||
|
* @param jwtId ID of the claim to view
|
||||||
|
*/
|
||||||
onClickLoadClaim(jwtId: string) {
|
onClickLoadClaim(jwtId: string) {
|
||||||
const route = {
|
const route = {
|
||||||
path: "/claim/" + encodeURIComponent(jwtId),
|
path: "/claim/" + encodeURIComponent(jwtId),
|
||||||
@@ -1065,16 +1205,31 @@ export default class HomeView extends Vue {
|
|||||||
this.$router.push(route);
|
this.$router.push(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats amount with currency code
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by giveDescription()
|
||||||
|
*/
|
||||||
displayAmount(code: string, amt: number) {
|
displayAmount(code: string, amt: number) {
|
||||||
return "" + amt + " " + this.currencyShortWordForCode(code, amt === 1);
|
return "" + amt + " " + this.currencyShortWordForCode(code, amt === 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets currency word based on code and plurality
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by displayAmount()
|
||||||
|
*/
|
||||||
currencyShortWordForCode(unitCode: string, single: boolean) {
|
currencyShortWordForCode(unitCode: string, single: boolean) {
|
||||||
return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode;
|
return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens dialog for creating new gift/claim
|
* Opens dialog for creating new gift/claim
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by template and openGiftedPrompts()
|
||||||
* @param giver Optional contact info for giver
|
* @param giver Optional contact info for giver
|
||||||
* @param description Optional gift description
|
* @param description Optional gift description
|
||||||
*/
|
*/
|
||||||
@@ -1093,7 +1248,9 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens prompts for gift ideas
|
* Opens prompts for gift ideas
|
||||||
* Links to openDialog for selected prompt
|
*
|
||||||
|
* @public
|
||||||
|
* Called by template click handler
|
||||||
*/
|
*/
|
||||||
openGiftedPrompts() {
|
openGiftedPrompts() {
|
||||||
(this.$refs.giftedPrompts as GiftedPrompts).open((giver, description) =>
|
(this.$refs.giftedPrompts as GiftedPrompts).open((giver, description) =>
|
||||||
@@ -1103,12 +1260,21 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens feed filter configuration
|
* Opens feed filter configuration
|
||||||
* @param reloadFeedOnChange Callback for when filters are updated
|
*
|
||||||
|
* @public
|
||||||
|
* Called by template click handler
|
||||||
*/
|
*/
|
||||||
openFeedFilters() {
|
openFeedFilters() {
|
||||||
(this.$refs.feedFilters as FeedFilters).open(this.reloadFeedOnChange);
|
(this.$refs.feedFilters as FeedFilters).open(this.reloadFeedOnChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows toast notification to user
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Used for various user notifications
|
||||||
|
* @param message Message to display
|
||||||
|
*/
|
||||||
toastUser(message: string) {
|
toastUser(message: string) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
@@ -1121,10 +1287,24 @@ export default class HomeView extends Vue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes CSS classes for known person icons
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Used in template for icon styling
|
||||||
|
* @param known Whether the person is known
|
||||||
|
* @returns CSS class string
|
||||||
|
*/
|
||||||
computeKnownPersonIconStyleClassNames(known: boolean) {
|
computeKnownPersonIconStyleClassNames(known: boolean) {
|
||||||
return known ? "text-slate-500" : "text-slate-100";
|
return known ? "text-slate-500" : "text-slate-100";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows name input dialog if needed
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by template click handler
|
||||||
|
*/
|
||||||
showNameThenIdDialog() {
|
showNameThenIdDialog() {
|
||||||
if (!this.givenName) {
|
if (!this.givenName) {
|
||||||
(this.$refs.userNameDialog as UserNameDialog).open(() => {
|
(this.$refs.userNameDialog as UserNameDialog).open(() => {
|
||||||
@@ -1135,6 +1315,12 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows dialog for sharing method selection
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called by showNameThenIdDialog()
|
||||||
|
*/
|
||||||
promptForShareMethod() {
|
promptForShareMethod() {
|
||||||
(this.$refs.choiceButtonDialog as ChoiceButtonDialog).open({
|
(this.$refs.choiceButtonDialog as ChoiceButtonDialog).open({
|
||||||
title: "How can you share your info?",
|
title: "How can you share your info?",
|
||||||
@@ -1154,6 +1340,14 @@ export default class HomeView extends Vue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches image data for sharing
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by ActivityListItem component
|
||||||
|
* @param event Event object
|
||||||
|
* @param imageUrl URL of image to cache
|
||||||
|
*/
|
||||||
async cacheImageData(event: Event, imageUrl: string) {
|
async cacheImageData(event: Event, imageUrl: string) {
|
||||||
try {
|
try {
|
||||||
// For images that might fail CORS, just store the URL
|
// For images that might fail CORS, just store the URL
|
||||||
@@ -1164,12 +1358,26 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens image viewer dialog
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by ActivityListItem component
|
||||||
|
* @param imageUrl URL of image to display
|
||||||
|
*/
|
||||||
async openImageViewer(imageUrl: string) {
|
async openImageViewer(imageUrl: string) {
|
||||||
this.selectedImageData = this.imageCache.get(imageUrl) ?? null;
|
this.selectedImageData = this.imageCache.get(imageUrl) ?? null;
|
||||||
this.selectedImage = imageUrl;
|
this.selectedImage = imageUrl;
|
||||||
this.isImageViewerOpen = true;
|
this.isImageViewerOpen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles claim confirmation
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* Called by ActivityListItem component
|
||||||
|
* @param record Record to confirm
|
||||||
|
*/
|
||||||
async confirmClaim(record: GiveRecordWithContactInfo) {
|
async confirmClaim(record: GiveRecordWithContactInfo) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"status": "failed",
|
||||||
|
"failedTests": []
|
||||||
|
}
|
||||||
29
test-playwright/test-results/.last-run.json
Normal file
29
test-playwright/test-results/.last-run.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"status": "failed",
|
||||||
|
"failedTests": [
|
||||||
|
"a29eb57667e0fb28c7e9-7a80e551e7f16a766d0d",
|
||||||
|
"a29eb57667e0fb28c7e9-1a8c76601bb6ea4f735c",
|
||||||
|
"a29eb57667e0fb28c7e9-0a3670fa77fcd5ac9827",
|
||||||
|
"a29eb57667e0fb28c7e9-90c8866cf70c7f96647d",
|
||||||
|
"a29eb57667e0fb28c7e9-4abc584edcf7a6a12389",
|
||||||
|
"a29eb57667e0fb28c7e9-3b443656a23fd8e7eb76",
|
||||||
|
"a29eb57667e0fb28c7e9-1f63cf7a41b756ffe01f",
|
||||||
|
"a29eb57667e0fb28c7e9-4eb03633761e58eac0a4",
|
||||||
|
"db48a48c514e3e2940e5-cef25040a0b285eed2ba",
|
||||||
|
"1c818805c9b0ac973736-726f18ba6163d57238c8",
|
||||||
|
"c52ae54d86eda05904f3-adf7525a07e75f4e3cc2",
|
||||||
|
"2fac21b9c9c3eb062631-9d2d2e9a199603c11b9b",
|
||||||
|
"64242279fe0133650483-20fbacc4e45c5561df6c",
|
||||||
|
"a7ff64a290be94f9d82c-e26ceb13031dafad1133",
|
||||||
|
"868977083268005e6ec0-c27d226d34e20ba4863d",
|
||||||
|
"5e149db5da4a5e319bcc-3298c84d0ebfff5e6d7c",
|
||||||
|
"5e149db5da4a5e319bcc-1981ba81641b6000f80b",
|
||||||
|
"2b5f6d3352de2040032d-bf5ed3a9483d90c396dd",
|
||||||
|
"2b5f6d3352de2040032d-6f52c3699c55c19ccad8",
|
||||||
|
"2b5f6d3352de2040032d-0f478a3208f64651daa1",
|
||||||
|
"2b5f6d3352de2040032d-a05f542cad739ee3b5b9",
|
||||||
|
"955bdfdfe05b442c0f5d-a9ec2b8bc7bd90ea0439",
|
||||||
|
"955bdfdfe05b442c0f5d-2c38171f673436923a8b",
|
||||||
|
"1a1fd29d3f0573e705e6-a3a6805908fe9a29ab11"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user