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.
		
		
		
		
		
			
		
			
				
					
					
						
							465 lines
						
					
					
						
							15 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							465 lines
						
					
					
						
							15 KiB
						
					
					
				
								/**
							 | 
						|
								 * DailyNotification Setup for TimeSafari PWA
							 | 
						|
								 * 
							 | 
						|
								 * This example shows exactly how to configure the DailyNotification plugin
							 | 
						|
								 * to work with your existing TimeSafari PWA request patterns, specifically
							 | 
						|
								 * the loadNewStarredProjectChanges() and getStarredProjectsWithChanges() methods.
							 | 
						|
								 * 
							 | 
						|
								 * @author Matthew Raymer
							 | 
						|
								 * @version 1.0.0
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								import { DailyNotification } from '@timesafari/daily-notification-plugin';
							 | 
						|
								import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin';
							 | 
						|
								import { AxiosInstance } from 'axios';
							 | 
						|
								
							 | 
						|
								// Your existing TimeSafari PWA interfaces
							 | 
						|
								interface PlanSummaryAndPreviousClaim {
							 | 
						|
								  id: string;
							 | 
						|
								  title: string;
							 | 
						|
								  description: string;
							 | 
						|
								  lastUpdated: string;
							 | 
						|
								  previousClaim?: unknown;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								interface StarredProjectsResponse {
							 | 
						|
								  data: Array<PlanSummaryAndPreviousClaim>;
							 | 
						|
								  hitLimit: boolean;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Your existing TimeSafari PWA class structure
							 | 
						|
								class TimeSafariHomeView {
							 | 
						|
								  // Your existing properties
							 | 
						|
								  activeDid = '';
							 | 
						|
								  starredPlanHandleIds: string[] = [];
							 | 
						|
								  lastAckedStarredPlanChangesJwtId = '';
							 | 
						|
								  numNewStarredProjectChanges = 0;
							 | 
						|
								  newStarredProjectChangesHitLimit = false;
							 | 
						|
								  apiServer = 'https://endorser.ch';
							 | 
						|
								  axios: AxiosInstance;
							 | 
						|
								  
							 | 
						|
								  // Plugin integration
							 | 
						|
								  private dailyNotificationService: DailyNotification | null = null;
							 | 
						|
								  private integrationService: TimeSafariIntegrationService | null = null;
							 | 
						|
								  
							 | 
						|
								  constructor(axiosInstance: AxiosInstance) {
							 | 
						|
								    this.axios = axiosInstance;
							 | 
						|
								  }
							 | 
						|
								  
							 | 
						|
								  /**
							 | 
						|
								   * DailyNotification Setup - This is what you need to add to your TimeSafari PWA
							 | 
						|
								   */
							 | 
						|
								  async setupDailyNotification(): Promise<void> {
							 | 
						|
								    try {
							 | 
						|
								      // Setup DailyNotification for TimeSafari PWA
							 | 
						|
								      
							 | 
						|
								      // Step 1: Configure the DailyNotification plugin
							 | 
						|
								      await DailyNotification.configure({
							 | 
						|
								        // Basic plugin configuration
							 | 
						|
								        storage: 'tiered',
							 | 
						|
								        ttlSeconds: 1800,
							 | 
						|
								        enableETagSupport: true,
							 | 
						|
								        enableErrorHandling: true,
							 | 
						|
								        enablePerformanceOptimization: true,
							 | 
						|
								        
							 | 
						|
								        // TimeSafari-specific configuration
							 | 
						|
								        timesafariConfig: {
							 | 
						|
								          // Required: 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 (same as your existing schedule)
							 | 
						|
								            maxResults: 50,
							 | 
						|
								            hitLimitHandling: 'warn'  // Same as your existing error handling
							 | 
						|
								          },
							 | 
						|
								          
							 | 
						|
								          // Sync configuration (optimized for your use case)
							 | 
						|
								          syncConfig: {
							 | 
						|
								            enableParallel: true,
							 | 
						|
								            maxConcurrent: 3,
							 | 
						|
								            batchSize: 10,
							 | 
						|
								            timeout: 30000,
							 | 
						|
								            retryAttempts: 3
							 | 
						|
								          },
							 | 
						|
								          
							 | 
						|
								          // Error policy (matches your existing error handling)
							 | 
						|
								          errorPolicy: {
							 | 
						|
								            maxRetries: 3,
							 | 
						|
								            backoffMultiplier: 2,
							 | 
						|
								            activeDidChangeRetries: 5,
							 | 
						|
								            starredProjectsRetries: 3
							 | 
						|
								          }
							 | 
						|
								        },
							 | 
						|
								        
							 | 
						|
								        // Network configuration using your existing axios instance
							 | 
						|
								        networkConfig: {
							 | 
						|
								          // Use your existing axios instance
							 | 
						|
								          httpClient: this.axios,
							 | 
						|
								          baseURL: this.apiServer,
							 | 
						|
								          timeout: 30000,
							 | 
						|
								          retryAttempts: 3,
							 | 
						|
								          retryDelay: 1000,
							 | 
						|
								          maxConcurrent: 5,
							 | 
						|
								          
							 | 
						|
								          // Headers matching your existing pattern
							 | 
						|
								          defaultHeaders: {
							 | 
						|
								            'Content-Type': 'application/json',
							 | 
						|
								            'Accept': 'application/json',
							 | 
						|
								            'User-Agent': 'TimeSafari-PWA/1.0.0'
							 | 
						|
								          }
							 | 
						|
								        },
							 | 
						|
								        
							 | 
						|
								        // Content fetch configuration (replaces your existing loadNewStarredProjectChanges)
							 | 
						|
								        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),
							 | 
						|
								            onComplete: this.handleStarredProjectsComplete.bind(this)
							 | 
						|
								          }
							 | 
						|
								        },
							 | 
						|
								        
							 | 
						|
								        // Authentication configuration
							 | 
						|
								        authentication: {
							 | 
						|
								          jwt: {
							 | 
						|
								            secret: process.env.JWT_SECRET || 'your-jwt-secret',
							 | 
						|
								            algorithm: 'HS256',
							 | 
						|
								            expirationMinutes: 60,
							 | 
						|
								            refreshThresholdMinutes: 10
							 | 
						|
								          }
							 | 
						|
								        },
							 | 
						|
								        
							 | 
						|
								        // Observability configuration
							 | 
						|
								        logging: {
							 | 
						|
								          level: 'INFO',
							 | 
						|
								          enableRequestLogging: true,
							 | 
						|
								          enableResponseLogging: true,
							 | 
						|
								          enableErrorLogging: true,
							 | 
						|
								          redactSensitiveData: true
							 | 
						|
								        },
							 | 
						|
								        
							 | 
						|
								        // Security configuration
							 | 
						|
								        security: {
							 | 
						|
								          certificatePinning: {
							 | 
						|
								            enabled: true,
							 | 
						|
								            pins: [
							 | 
						|
								              {
							 | 
						|
								                hostname: 'endorser.ch',
							 | 
						|
								                pins: ['sha256/YOUR_PIN_HERE']
							 | 
						|
								              }
							 | 
						|
								            ]
							 | 
						|
								          }
							 | 
						|
								        }
							 | 
						|
								      });
							 | 
						|
								      
							 | 
						|
								      // Step 2: Initialize TimeSafari Integration Service
							 | 
						|
								      this.integrationService = TimeSafariIntegrationService.getInstance();
							 | 
						|
								      await this.integrationService.initialize({
							 | 
						|
								        activeDid: this.activeDid,
							 | 
						|
								        storageAdapter: this.getTimeSafariStorageAdapter(),
							 | 
						|
								        endorserApiBaseUrl: this.apiServer,
							 | 
						|
								        
							 | 
						|
								        // Use your existing request patterns
							 | 
						|
								        requestConfig: {
							 | 
						|
								          httpClient: this.axios,
							 | 
						|
								          baseURL: this.apiServer,
							 | 
						|
								          timeout: 30000,
							 | 
						|
								          retryAttempts: 3
							 | 
						|
								        },
							 | 
						|
								        
							 | 
						|
								        // Configure starred projects fetching
							 | 
						|
								        starredProjectsConfig: {
							 | 
						|
								          enabled: true,
							 | 
						|
								          starredPlanHandleIds: this.starredPlanHandleIds,
							 | 
						|
								          lastAckedJwtId: this.lastAckedStarredPlanChangesJwtId,
							 | 
						|
								          fetchInterval: '0 8 * * *',
							 | 
						|
								          maxResults: 50
							 | 
						|
								        }
							 | 
						|
								      });
							 | 
						|
								      
							 | 
						|
								      // Step 3: Schedule daily notifications
							 | 
						|
								      await DailyNotification.scheduleDailyNotification({
							 | 
						|
								        title: 'TimeSafari Community Update',
							 | 
						|
								        body: 'You have new offers and project updates',
							 | 
						|
								        time: '09:00',
							 | 
						|
								        channel: 'timesafari_community_updates'
							 | 
						|
								      });
							 | 
						|
								      
							 | 
						|
								      // DailyNotification setup completed successfully
							 | 
						|
								      
							 | 
						|
								    } catch (error) {
							 | 
						|
								      console.error('Failed to setup DailyNotification:', error);
							 | 
						|
								      throw error;
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								  
							 | 
						|
								  /**
							 | 
						|
								   * Enhanced version of your existing loadNewStarredProjectChanges method
							 | 
						|
								   * 
							 | 
						|
								   * This replaces your existing method with plugin-enhanced functionality
							 | 
						|
								   * while maintaining the same interface and behavior.
							 | 
						|
								   */
							 | 
						|
								  async loadNewStarredProjectChanges(): Promise<void> {
							 | 
						|
								    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
							 | 
						|
								        );
							 | 
						|
								        
							 | 
						|
								        if (!starredProjectChanges) {
							 | 
						|
								          this.numNewStarredProjectChanges = 0;
							 | 
						|
								          this.newStarredProjectChangesHitLimit = false;
							 | 
						|
								          return;
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        // Same handling as your existing code
							 | 
						|
								        this.numNewStarredProjectChanges = starredProjectChanges.data.length;
							 | 
						|
								        this.newStarredProjectChangesHitLimit = starredProjectChanges.hitLimit;
							 | 
						|
								        
							 | 
						|
								        // Enhanced logging (optional)
							 | 
						|
								        // Starred projects loaded successfully
							 | 
						|
								        
							 | 
						|
								      } 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;
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								  
							 | 
						|
								  /**
							 | 
						|
								   * Callback handlers that match your existing error handling patterns
							 | 
						|
								   */
							 | 
						|
								  async handleStarredProjectsSuccess(data: StarredProjectsResponse): Promise<void> {
							 | 
						|
								    // Same handling as your existing code
							 | 
						|
								    this.numNewStarredProjectChanges = data.data.length;
							 | 
						|
								    this.newStarredProjectChangesHitLimit = data.hitLimit;
							 | 
						|
								    
							 | 
						|
								    // Update UI (your existing method)
							 | 
						|
								    this.updateStarredProjectsUI(data);
							 | 
						|
								    
							 | 
						|
								    // Enhanced logging (optional)
							 | 
						|
								    // Starred projects success callback
							 | 
						|
								  }
							 | 
						|
								  
							 | 
						|
								  async handleStarredProjectsError(error: Error): Promise<void> {
							 | 
						|
								    // Same error handling as your existing code
							 | 
						|
								    console.warn('[HomeView] Failed to load starred project changes:', error);
							 | 
						|
								    this.numNewStarredProjectChanges = 0;
							 | 
						|
								    this.newStarredProjectChangesHitLimit = false;
							 | 
						|
								    
							 | 
						|
								    // Enhanced error handling (optional)
							 | 
						|
								    console.error('Starred projects error callback:', {
							 | 
						|
								      error: error.message,
							 | 
						|
								      activeDid: this.activeDid,
							 | 
						|
								      planCount: this.starredPlanHandleIds.length
							 | 
						|
								    });
							 | 
						|
								  }
							 | 
						|
								  
							 | 
						|
								  async handleStarredProjectsComplete(_result: unknown): Promise<void> {
							 | 
						|
								    // Handle completion
							 | 
						|
								    // Starred projects fetch completed
							 | 
						|
								  }
							 | 
						|
								  
							 | 
						|
								  /**
							 | 
						|
								   * Your existing methods (unchanged)
							 | 
						|
								   */
							 | 
						|
								  private updateStarredProjectsUI(_data: StarredProjectsResponse): void {
							 | 
						|
								    // Your existing UI update logic
							 | 
						|
								    // Updating UI with starred projects data
							 | 
						|
								  }
							 | 
						|
								  
							 | 
						|
								  private getTimeSafariStorageAdapter(): unknown {
							 | 
						|
								    // Return your existing TimeSafari storage adapter
							 | 
						|
								    return {
							 | 
						|
								      // Your existing storage adapter implementation
							 | 
						|
								    };
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Usage example - This is what you add to your TimeSafari PWA
							 | 
						|
								export async function setupDailyNotificationForTimeSafari(
							 | 
						|
								  axiosInstance: AxiosInstance,
							 | 
						|
								  activeDid: string,
							 | 
						|
								  starredPlanHandleIds: string[],
							 | 
						|
								  lastAckedJwtId: string,
							 | 
						|
								  apiServer = 'https://endorser.ch'
							 | 
						|
								): Promise<TimeSafariHomeView> {
							 | 
						|
								  
							 | 
						|
								  // Setting up DailyNotification for TimeSafari PWA
							 | 
						|
								  
							 | 
						|
								  // Create your existing HomeView instance
							 | 
						|
								  const homeView = new TimeSafariHomeView(axiosInstance);
							 | 
						|
								  
							 | 
						|
								  // Set up your existing TimeSafari data
							 | 
						|
								  homeView.activeDid = activeDid;
							 | 
						|
								  homeView.starredPlanHandleIds = starredPlanHandleIds;
							 | 
						|
								  homeView.lastAckedStarredPlanChangesJwtId = lastAckedJwtId;
							 | 
						|
								  homeView.apiServer = apiServer;
							 | 
						|
								  
							 | 
						|
								  // Setup DailyNotification plugin
							 | 
						|
								  await homeView.setupDailyNotification();
							 | 
						|
								  
							 | 
						|
								  // Test the enhanced method
							 | 
						|
								  await homeView.loadNewStarredProjectChanges();
							 | 
						|
								  
							 | 
						|
								  // DailyNotification setup completed successfully
							 | 
						|
								  
							 | 
						|
								  return homeView;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Vue.js component integration example
							 | 
						|
								export const TimeSafariDailyNotificationMixin = {
							 | 
						|
								  data(): Record<string, unknown> {
							 | 
						|
								    return {
							 | 
						|
								      // Your existing data
							 | 
						|
								      activeDid: '',
							 | 
						|
								      starredPlanHandleIds: [] as string[],
							 | 
						|
								      lastAckedStarredPlanChangesJwtId: '',
							 | 
						|
								      numNewStarredProjectChanges: 0,
							 | 
						|
								      newStarredProjectChangesHitLimit: false,
							 | 
						|
								      
							 | 
						|
								      // Plugin integration
							 | 
						|
								      dailyNotificationService: null as DailyNotification | null,
							 | 
						|
								      integrationService: null as TimeSafariIntegrationService | null
							 | 
						|
								    };
							 | 
						|
								  },
							 | 
						|
								  
							 | 
						|
								  async mounted(): Promise<void> {
							 | 
						|
								    // Setup DailyNotification when component mounts
							 | 
						|
								    await this.setupDailyNotification();
							 | 
						|
								  },
							 | 
						|
								  
							 | 
						|
								  methods: {
							 | 
						|
								    async setupDailyNotification(): Promise<void> {
							 | 
						|
								      try {
							 | 
						|
								        // Configure DailyNotification plugin
							 | 
						|
								        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,
							 | 
						|
								              onError: this.handleStarredProjectsError
							 | 
						|
								            }
							 | 
						|
								          }
							 | 
						|
								        });
							 | 
						|
								        
							 | 
						|
								        // Initialize integration service
							 | 
						|
								        this.integrationService = TimeSafariIntegrationService.getInstance();
							 | 
						|
								        await this.integrationService.initialize({
							 | 
						|
								          activeDid: this.activeDid,
							 | 
						|
								          storageAdapter: this.getTimeSafariStorageAdapter(),
							 | 
						|
								          endorserApiBaseUrl: this.apiServer
							 | 
						|
								        });
							 | 
						|
								        
							 | 
						|
								      } catch (error) {
							 | 
						|
								        console.error('Failed to setup DailyNotification:', error);
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								    
							 | 
						|
								    // Your existing methods (enhanced)
							 | 
						|
								    async loadNewStarredProjectChanges(): Promise<void> {
							 | 
						|
								      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;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								    
							 | 
						|
								    handleStarredProjectsSuccess(data: StarredProjectsResponse): void {
							 | 
						|
								      this.numNewStarredProjectChanges = data.data.length;
							 | 
						|
								      this.newStarredProjectChangesHitLimit = data.hitLimit;
							 | 
						|
								      this.updateStarredProjectsUI(data);
							 | 
						|
								    },
							 | 
						|
								    
							 | 
						|
								    handleStarredProjectsError(error: Error): void {
							 | 
						|
								      console.warn('[HomeView] Failed to load starred project changes:', error);
							 | 
						|
								      this.numNewStarredProjectChanges = 0;
							 | 
						|
								      this.newStarredProjectChangesHitLimit = false;
							 | 
						|
								    },
							 | 
						|
								    
							 | 
						|
								    // Your existing methods
							 | 
						|
								    updateStarredProjectsUI(_data: StarredProjectsResponse): void {
							 | 
						|
								      // Your existing UI update logic
							 | 
						|
								    },
							 | 
						|
								    
							 | 
						|
								    getTimeSafariStorageAdapter(): unknown {
							 | 
						|
								      // Your existing storage adapter
							 | 
						|
								      return {};
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								// Export for use in your TimeSafari PWA
							 | 
						|
								export { TimeSafariHomeView };
							 | 
						|
								
							 |