Browse Source
- Add comprehensive setup guide showing exact configuration for TimeSafari PWA - Provide step-by-step instructions for integrating with existing loadNewStarredProjectChanges() - Include complete working example with all configuration options - Show Vue.js component integration patterns - Add troubleshooting and testing guidance - Demonstrate how to maintain existing interfaces while adding plugin features This provides a practical, copy-paste ready setup for TimeSafari PWA integration.master
2 changed files with 853 additions and 0 deletions
@ -0,0 +1,387 @@ |
|||
# 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 |
|||
|
|||
```bash |
|||
# 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 |
|||
|
|||
```typescript |
|||
// 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: |
|||
|
|||
```typescript |
|||
// 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: |
|||
|
|||
```typescript |
|||
// 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: |
|||
|
|||
```typescript |
|||
// 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: |
|||
|
|||
```typescript |
|||
// 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: |
|||
|
|||
```typescript |
|||
// 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: |
|||
|
|||
```typescript |
|||
// 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: |
|||
|
|||
```typescript |
|||
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. |
@ -0,0 +1,466 @@ |
|||
/** |
|||
* 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: string = ''; |
|||
starredPlanHandleIds: string[] = []; |
|||
lastAckedStarredPlanChangesJwtId: string = ''; |
|||
numNewStarredProjectChanges: number = 0; |
|||
newStarredProjectChangesHitLimit: boolean = false; |
|||
apiServer: string = '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 { |
|||
console.log('Setting up 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' |
|||
}); |
|||
|
|||
console.log('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 |
|||
); |
|||
|
|||
// Same handling as your existing code
|
|||
this.numNewStarredProjectChanges = starredProjectChanges.data.length; |
|||
this.newStarredProjectChangesHitLimit = starredProjectChanges.hitLimit; |
|||
|
|||
// Enhanced logging (optional)
|
|||
console.log('Starred projects loaded successfully:', { |
|||
count: this.numNewStarredProjectChanges, |
|||
hitLimit: this.newStarredProjectChangesHitLimit, |
|||
planIds: this.starredPlanHandleIds.length |
|||
}); |
|||
|
|||
} 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)
|
|||
console.log('Starred projects success callback:', { |
|||
count: data.data.length, |
|||
hitLimit: data.hitLimit |
|||
}); |
|||
} |
|||
|
|||
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
|
|||
console.log('Starred projects fetch completed:', result); |
|||
} |
|||
|
|||
/** |
|||
* Your existing methods (unchanged) |
|||
*/ |
|||
private updateStarredProjectsUI(data: StarredProjectsResponse): void { |
|||
// Your existing UI update logic
|
|||
console.log('Updating UI with starred projects data:', 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: string = 'https://endorser.ch' |
|||
): Promise<TimeSafariHomeView> { |
|||
|
|||
console.log('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(); |
|||
|
|||
console.log('DailyNotification setup completed successfully!'); |
|||
|
|||
return homeView; |
|||
} |
|||
|
|||
// Vue.js component integration example
|
|||
export const TimeSafariDailyNotificationMixin = { |
|||
data() { |
|||
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() { |
|||
// Setup DailyNotification when component mounts
|
|||
await this.setupDailyNotification(); |
|||
}, |
|||
|
|||
methods: { |
|||
async setupDailyNotification() { |
|||
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() { |
|||
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) { |
|||
this.numNewStarredProjectChanges = data.data.length; |
|||
this.newStarredProjectChangesHitLimit = data.hitLimit; |
|||
this.updateStarredProjectsUI(data); |
|||
}, |
|||
|
|||
handleStarredProjectsError(error: Error) { |
|||
console.warn('[HomeView] Failed to load starred project changes:', error); |
|||
this.numNewStarredProjectChanges = 0; |
|||
this.newStarredProjectChangesHitLimit = false; |
|||
}, |
|||
|
|||
// Your existing methods
|
|||
updateStarredProjectsUI(data: StarredProjectsResponse) { |
|||
// Your existing UI update logic
|
|||
}, |
|||
|
|||
getTimeSafariStorageAdapter() { |
|||
// Your existing storage adapter
|
|||
return {}; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
// Export for use in your TimeSafari PWA
|
|||
export { TimeSafariHomeView }; |
Loading…
Reference in new issue