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
- Plugin not found: Make sure you've installed the plugin correctly
- Configuration errors: Check that all required fields are provided
- Network errors: Verify your axios instance and API server URL
- 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
- Test the integration with your existing TimeSafari PWA code
- Compare results between your existing method and the plugin-enhanced version
- Gradually migrate other request methods to use the plugin
- 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.