You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

12 KiB

DailyNotification Setup Guide for TimeSafari PWA

Author: Matthew Raymer
Version: 1.0.0
Created: 2025-10-08 06:24:57 UTC

Overview

This guide shows you exactly how to set up the DailyNotification plugin in your existing TimeSafari PWA to work with your current loadNewStarredProjectChanges() and getStarredProjectsWithChanges() methods.

Step-by-Step Setup

Step 1: Install the Plugin

# In your TimeSafari PWA project
npm install ssh://git@173.199.124.46:222/trent_larson/daily-notification-plugin.git

Step 2: Import the Plugin

// In your TimeSafari PWA file (e.g., HomeView.vue or main.ts)
import { DailyNotification } from '@timesafari/daily-notification-plugin';
import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin';

Step 3: Configure the Plugin

Add this configuration to your existing TimeSafari PWA code:

// In your TimeSafari PWA class/component
async setupDailyNotification() {
  try {
    // Configure the plugin with your existing TimeSafari settings
    await DailyNotification.configure({
      // Basic configuration
      storage: 'tiered',
      ttlSeconds: 1800,
      enableETagSupport: true,
      
      // TimeSafari-specific configuration
      timesafariConfig: {
        // Your existing activeDid
        activeDid: this.activeDid,
        
        // Your existing API endpoints
        endpoints: {
          offersToPerson: `${this.apiServer}/api/v2/offers/person`,
          offersToPlans: `${this.apiServer}/api/v2/offers/plans`,
          projectsLastUpdated: `${this.apiServer}/api/v2/report/plansLastUpdatedBetween`
        },
        
        // Configure starred projects fetching (matches your existing pattern)
        starredProjectsConfig: {
          enabled: true,
          starredPlanHandleIds: this.starredPlanHandleIds,
          lastAckedJwtId: this.lastAckedStarredPlanChangesJwtId,
          fetchInterval: '0 8 * * *',  // Daily at 8 AM
          maxResults: 50,
          hitLimitHandling: 'warn'
        }
      },
      
      // Network configuration using your existing axios instance
      networkConfig: {
        httpClient: this.axios,        // Your existing axios instance
        baseURL: this.apiServer,       // Your existing API server
        timeout: 30000,
        retryAttempts: 3
      },
      
      // Content fetch configuration (replaces your existing method)
      contentFetch: {
        enabled: true,
        schedule: '0 8 * * *',  // Daily at 8 AM
        
        // Your existing request pattern
        requestConfig: {
          method: 'POST',
          url: `${this.apiServer}/api/v2/report/plansLastUpdatedBetween`,
          headers: {
            'Authorization': 'Bearer ${jwt}',
            'X-User-DID': '${activeDid}',
            'Content-Type': 'application/json'
          },
          body: {
            planIds: '${starredPlanHandleIds}',
            afterId: '${lastAckedJwtId}'
          }
        },
        
        // Callbacks that match your existing error handling
        callbacks: {
          onSuccess: this.handleStarredProjectsSuccess.bind(this),
          onError: this.handleStarredProjectsError.bind(this)
        }
      }
    });
    
    // Initialize TimeSafari Integration Service
    this.integrationService = TimeSafariIntegrationService.getInstance();
    await this.integrationService.initialize({
      activeDid: this.activeDid,
      storageAdapter: this.getTimeSafariStorageAdapter(),
      endorserApiBaseUrl: this.apiServer
    });
    
    console.log('DailyNotification setup completed successfully!');
    
  } catch (error) {
    console.error('Failed to setup DailyNotification:', error);
  }
}

Step 4: Replace Your Existing Method

Replace your existing loadNewStarredProjectChanges() method with this enhanced version:

// Enhanced version of your existing method
async loadNewStarredProjectChanges() {
  if (this.activeDid && this.starredPlanHandleIds.length > 0) {
    try {
      // Use plugin's enhanced fetching with same interface as your existing code
      const starredProjectChanges = await this.integrationService.getStarredProjectsWithChanges(
        this.activeDid,
        this.starredPlanHandleIds,
        this.lastAckedStarredPlanChangesJwtId
      );
      
      // Same handling as your existing code
      this.numNewStarredProjectChanges = starredProjectChanges.data.length;
      this.newStarredProjectChangesHitLimit = starredProjectChanges.hitLimit;
      
    } catch (error) {
      // Same error handling as your existing code
      console.warn('[HomeView] Failed to load starred project changes:', error);
      this.numNewStarredProjectChanges = 0;
      this.newStarredProjectChangesHitLimit = false;
    }
  } else {
    this.numNewStarredProjectChanges = 0;
    this.newStarredProjectChangesHitLimit = false;
  }
}

Step 5: Add Callback Handlers

Add these callback handlers that match your existing error handling patterns:

// Callback handlers that match your existing error handling
async handleStarredProjectsSuccess(data: { data: Array<PlanSummaryAndPreviousClaim>; hitLimit: boolean }) {
  // Same handling as your existing code
  this.numNewStarredProjectChanges = data.data.length;
  this.newStarredProjectChangesHitLimit = data.hitLimit;
  
  // Update UI (your existing method)
  this.updateStarredProjectsUI(data);
}

async handleStarredProjectsError(error: Error) {
  // Same error handling as your existing code
  console.warn('[HomeView] Failed to load starred project changes:', error);
  this.numNewStarredProjectChanges = 0;
  this.newStarredProjectChangesHitLimit = false;
}

Step 6: Initialize in Your Component

Add the setup to your existing TimeSafari PWA component:

// In your existing TimeSafari PWA component (e.g., HomeView.vue)
export default defineComponent({
  name: 'HomeView',
  
  data() {
    return {
      // Your existing data
      activeDid: '',
      starredPlanHandleIds: [] as string[],
      lastAckedStarredPlanChangesJwtId: '',
      numNewStarredProjectChanges: 0,
      newStarredProjectChangesHitLimit: false,
      
      // Plugin integration
      integrationService: null as TimeSafariIntegrationService | null
    };
  },
  
  async mounted() {
    // Setup DailyNotification when component mounts
    await this.setupDailyNotification();
  },
  
  methods: {
    // Add the setupDailyNotification method from Step 3
    async setupDailyNotification() { /* ... */ },
    
    // Replace your existing loadNewStarredProjectChanges with Step 4 version
    async loadNewStarredProjectChanges() { /* ... */ },
    
    // Add callback handlers from Step 5
    async handleStarredProjectsSuccess(data) { /* ... */ },
    async handleStarredProjectsError(error) { /* ... */ },
    
    // Your existing methods (unchanged)
    updateStarredProjectsUI(data) { /* ... */ },
    getTimeSafariStorageAdapter() { /* ... */ }
  }
});

Complete Example

Here's a complete example showing how to integrate the plugin into your existing TimeSafari PWA:

// Complete integration example
import { DailyNotification } from '@timesafari/daily-notification-plugin';
import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin';

class TimeSafariHomeView {
  // Your existing properties
  activeDid: string = '';
  starredPlanHandleIds: string[] = [];
  lastAckedStarredPlanChangesJwtId: string = '';
  numNewStarredProjectChanges: number = 0;
  newStarredProjectChangesHitLimit: boolean = false;
  apiServer: string = 'https://endorser.ch';
  axios: AxiosInstance;
  
  // Plugin integration
  private integrationService: TimeSafariIntegrationService | null = null;
  
  constructor(axiosInstance: AxiosInstance) {
    this.axios = axiosInstance;
  }
  
  async setupDailyNotification() {
    await DailyNotification.configure({
      timesafariConfig: {
        activeDid: this.activeDid,
        endpoints: {
          projectsLastUpdated: `${this.apiServer}/api/v2/report/plansLastUpdatedBetween`
        },
        starredProjectsConfig: {
          enabled: true,
          starredPlanHandleIds: this.starredPlanHandleIds,
          lastAckedJwtId: this.lastAckedStarredPlanChangesJwtId,
          fetchInterval: '0 8 * * *'
        }
      },
      networkConfig: {
        httpClient: this.axios,
        baseURL: this.apiServer,
        timeout: 30000
      },
      contentFetch: {
        enabled: true,
        schedule: '0 8 * * *',
        callbacks: {
          onSuccess: this.handleStarredProjectsSuccess.bind(this),
          onError: this.handleStarredProjectsError.bind(this)
        }
      }
    });
    
    this.integrationService = TimeSafariIntegrationService.getInstance();
    await this.integrationService.initialize({
      activeDid: this.activeDid,
      storageAdapter: this.getTimeSafariStorageAdapter(),
      endorserApiBaseUrl: this.apiServer
    });
  }
  
  async loadNewStarredProjectChanges() {
    if (this.activeDid && this.starredPlanHandleIds.length > 0) {
      try {
        const starredProjectChanges = await this.integrationService!.getStarredProjectsWithChanges(
          this.activeDid,
          this.starredPlanHandleIds,
          this.lastAckedStarredPlanChangesJwtId
        );
        
        this.numNewStarredProjectChanges = starredProjectChanges.data.length;
        this.newStarredProjectChangesHitLimit = starredProjectChanges.hitLimit;
        
      } catch (error) {
        console.warn('[HomeView] Failed to load starred project changes:', error);
        this.numNewStarredProjectChanges = 0;
        this.newStarredProjectChangesHitLimit = false;
      }
    } else {
      this.numNewStarredProjectChanges = 0;
      this.newStarredProjectChangesHitLimit = false;
    }
  }
  
  async handleStarredProjectsSuccess(data: { data: Array<PlanSummaryAndPreviousClaim>; hitLimit: boolean }) {
    this.numNewStarredProjectChanges = data.data.length;
    this.newStarredProjectChangesHitLimit = data.hitLimit;
    this.updateStarredProjectsUI(data);
  }
  
  async handleStarredProjectsError(error: Error) {
    console.warn('[HomeView] Failed to load starred project changes:', error);
    this.numNewStarredProjectChanges = 0;
    this.newStarredProjectChangesHitLimit = false;
  }
  
  // Your existing methods (unchanged)
  private updateStarredProjectsUI(data: { data: Array<PlanSummaryAndPreviousClaim>; hitLimit: boolean }) {
    // Your existing UI update logic
  }
  
  private getTimeSafariStorageAdapter() {
    // Your existing storage adapter
    return {};
  }
}

What You Get

After following this setup, you'll have:

Same Interface: Your existing loadNewStarredProjectChanges() method works exactly the same Enhanced Features: Background fetching, structured logging, metrics Better Error Handling: Enhanced error handling with retry logic Performance Improvements: Caching, batching, and optimization Observability: Structured logging with event IDs and metrics Background Notifications: Daily notifications with your starred projects data

Testing

Test the integration by calling your existing method:

// Test the enhanced method
await homeView.loadNewStarredProjectChanges();

// Check the results (same as before)
console.log('New starred project changes:', homeView.numNewStarredProjectChanges);
console.log('Hit limit:', homeView.newStarredProjectChangesHitLimit);

Troubleshooting

Common Issues

  1. Plugin not found: Make sure you've installed the plugin correctly
  2. Configuration errors: Check that all required fields are provided
  3. Network errors: Verify your axios instance and API server URL
  4. Authentication errors: Check your JWT token and activeDid

Debug Mode

Enable debug logging to troubleshoot issues:

await DailyNotification.configure({
  logging: {
    level: 'DEBUG',
    enableRequestLogging: true,
    enableResponseLogging: true,
    enableErrorLogging: true
  }
});

Next Steps

  1. Test the integration with your existing TimeSafari PWA code
  2. Compare results between your existing method and the plugin-enhanced version
  3. Gradually migrate other request methods to use the plugin
  4. Leverage advanced features like background fetching and observability

That's it! Your TimeSafari PWA now has enhanced daily notification capabilities while maintaining the same interface and behavior you're already familiar with.