@medha-analytics/onevoice
v1.0.1
Published
OneVoice Feedback Library - A reusable Angular library for collecting user feedback with prefill, field locking, and screenshot capture support
Maintainers
Readme
@medha-analytics/onevoice
A powerful, flexible Angular library for collecting user feedback with support for pre-filling, field locking, and screenshot capture.
Features
✅ Easy Integration - Simple forRoot configuration pattern like Angular modules ✅ Pre-fill Support - Pre-populate any field with static values or functions ✅ Field Locking - Make fields read-only (perfect for hardcoding application name) ✅ Screenshot Auto-Capture - Attach screenshots programmatically ✅ Multiple Placement Modes - Embedded form, floating button, or modal ✅ Programmatic API - Open feedback form from anywhere in your app ✅ TypeScript Support - Full type definitions included ✅ Customizable - Configure labels, placeholders, categories, and styling
Installation
npm install @medha-analytics/onevoiceQuick Start
1. Import and Configure in app.config.ts
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { OneVoiceModule } from '@medha-analytics/onevoice';
import { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
importProvidersFrom(
OneVoiceModule.forRoot({
backendUrl: 'http://localhost:9099',
applicationName: 'AIRO', // Hardcoded per app
fields: {
application: {
prefill: 'AIRO',
locked: true // Users cannot change this
}
},
getUserId: () => localStorage.getItem('userId') || 'anonymous',
getAuthToken: () => localStorage.getItem('idToken') || ''
})
)
]
};2. Use the Components
Embedded Form
<!-- feedback-page.component.html -->
<onevoice-feedback-form></onevoice-feedback-form>Floating Button (Global)
<!-- app.component.html -->
<router-outlet></router-outlet>
<onevoice-feedback-button position="bottom-right"></onevoice-feedback-button>Programmatic API
import { Component } from '@angular/core';
import { OneVoiceService } from '@medha-analytics/onevoice';
@Component({
selector: 'app-dashboard',
template: `<button (click)="reportIssue()">Report Dashboard Issue</button>`
})
export class DashboardComponent {
constructor(private oneVoice: OneVoiceService) {}
reportIssue() {
this.oneVoice.openFeedbackForm({
prefillData: {
title: 'Issue on Analytics Dashboard',
category: 'Bug Report',
description: 'Page: Dashboard\nURL: ' + window.location.href
},
mode: 'modal'
});
}
}Configuration
OneVoiceConfig Interface
interface OneVoiceConfig {
backendUrl: string; // Required: Backend API URL
applicationName: string; // Required: Application identifier
tenant?: string; // Optional: Tenant ID (default: 'medha-analytics')
fields?: {
title?: FieldConfig;
category?: CategoryFieldConfig;
description?: FieldConfig;
attachments?: AttachmentConfig;
application?: FieldConfig;
};
ui?: {
theme?: 'light' | 'dark';
primaryColor?: string;
floatingButton?: FloatingButtonConfig;
};
getUserId?: () => string; // Function to get current user ID
getAuthToken?: () => string; // Function to get auth token
}Field Configuration
interface FieldConfig {
required?: boolean; // Is field required
label?: string; // Custom label
placeholder?: string; // Placeholder text
visible?: boolean; // Show/hide field
prefill?: string | (() => string | Promise<string>); // Pre-fill value
locked?: boolean; // Make read-only
}Usage Examples
Example 1: Basic Setup with Locked Application
OneVoiceModule.forRoot({
backendUrl: 'http://localhost:9099',
applicationName: 'AIRO',
fields: {
application: {
prefill: 'AIRO',
locked: true
}
}
})Example 2: Contextual Feedback with Screenshot
async reportPageIssue() {
const screenshot = await this.captureScreenshot();
this.oneVoice.openFeedbackForm({
prefillData: {
title: 'Issue on Dashboard Page',
category: 'Bug Report',
description: 'Found an issue on this page...',
attachments: [screenshot] // Pre-attached!
},
lockedFields: ['application'],
mode: 'modal'
});
}Example 3: Multiple Placement Points
<!-- Global floating button -->
<onevoice-feedback-button position="bottom-right"></onevoice-feedback-button>
<!-- Navbar link -->
<a (click)="openFeedback()">Feedback</a>
<!-- Contextual button -->
<button (click)="reportDashboardIssue()">Report Issue</button>Components
FeedbackFormComponent
Selector: onevoice-feedback-form
Inputs:
prefillData?: Partial<FeedbackData>- Pre-fill form datalockedFields?: string[]- Array of field names to lockshowTitle?: boolean- Show/hide title (default: true)standalone?: boolean- Standalone mode (default: true)
Outputs:
onSubmitSuccess: EventEmitter<any>- Emitted on successful submissiononSubmitError: EventEmitter<any>- Emitted on submission erroronCancel: EventEmitter<void>- Emitted when user cancels
FeedbackButtonComponent
Selector: onevoice-feedback-button
Inputs:
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'label?: string- Button tooltip labelicon?: string- Custom icon URLbackgroundColor?: string- Custom background colorautoCapture?: boolean- Auto-capture screenshot on open
Services
OneVoiceService
Methods:
openFeedbackForm(options: OpenFeedbackOptions)- Opens feedback form programmaticallysubmitFeedback(payload: FeedbackPayload): Observable<any>- Submit feedback to backenduploadFiles(feedbackId: number, files: File[]): Promise<any>- Upload filesgetUserId(): string- Get current user IDgetAuthToken(): string | null- Get authentication token
Backend API
The library expects the following backend endpoints:
POST /feedback/add
Submit new feedback.
POST /feedback/upload-files/:feedbackId
Upload files for a feedback (query param: user_id).
Building and Publishing
Build the Library
cd onevoice-library/onevoice-workspace
ng build onevoiceBuild artifacts will be in dist/onevoice/.
Publish to npm
cd dist/onevoice
npm publishLicense
MIT
Support
For issues, questions, or feature requests, please contact Medha Analytics.
Changelog
v1.0.0
- Initial release
- Feedback form component with prefill and lock support
- Floating button component
- Programmatic API
- Field-level configuration
- Multiple placement modes
