285 lines
8.5 KiB
Markdown
285 lines
8.5 KiB
Markdown
# Modal Dialog Implementation Documentation
|
|
|
|
## Overview
|
|
|
|
This document describes the implementation of two configurable modal dialog systems for the desktop-angular project:
|
|
|
|
1) Angular in-app modal component (already integrated into the UI)
|
|
2) Electron-native modal window (opens a frameless BrowserWindow as a dialog)
|
|
|
|
Both allow variable questions, 1-3 buttons with custom labels, and return metadata for the clicked button. The Electron-native dialog additionally supports color customization for background, text, button colors per dialog.
|
|
|
|
## Files Added/Modified
|
|
|
|
### 1. New Files Created
|
|
|
|
#### `src/frontend/src/app/modal.service.ts`
|
|
|
|
**Purpose**: Core service for managing modal dialogs
|
|
**What it does**:
|
|
|
|
- Defines interfaces for modal configuration (`ModalConfig`, `ModalButton`, `ModalResult`)
|
|
- Provides `ModalService` with methods to show/hide modals
|
|
- Returns promises that resolve with button click results
|
|
- Includes convenience methods for common dialog types
|
|
|
|
**Key Features**:
|
|
|
|
- `show(config: ModalConfig): Promise<ModalResult>` - Main method to show custom modals
|
|
- `showConfirm(title, message): Promise<boolean>` - Yes/No confirmation dialog
|
|
- `showYesNoCancel(title, message): Promise<'yes'|'no'|'cancel'>` - Three-option dialog
|
|
- `showInfo(title, message): Promise<void>` - Information dialog with OK button
|
|
|
|
#### `src/frontend/src/app/modal.component.ts`
|
|
|
|
**Purpose**: Angular component that renders the modal dialog
|
|
**What it does**:
|
|
|
|
- Displays modal overlay and dialog box
|
|
- Renders configurable buttons with different styles
|
|
- Handles button clicks and communicates with service
|
|
- Manages modal visibility through service subscription
|
|
|
|
**Key Features**:
|
|
|
|
- Standalone Angular component
|
|
- Reactive to service state changes
|
|
- Supports button styling (primary, secondary, danger)
|
|
- Overlay click handling (currently disabled)
|
|
|
|
#### `src/frontend/src/app/modal.component.scss`
|
|
|
|
**Purpose**: Styling for the modal dialog
|
|
**What it does**:
|
|
|
|
- Creates modal overlay with semi-transparent background
|
|
- Styles dialog box with footer-matching colors (#aa1c3a)
|
|
- Implements button styles matching the app's footer buttons
|
|
- Provides responsive design for mobile devices
|
|
|
|
**Key Features**:
|
|
|
|
- Modal overlay with backdrop
|
|
- Dialog box with header, body, and footer sections
|
|
- Button styles matching app footer (white background, red text)
|
|
- Three button style variants: primary, secondary, danger
|
|
- Mobile-responsive design
|
|
|
|
### 2. Modified Files
|
|
|
|
#### `src/frontend/src/app/root.component.ts`
|
|
|
|
**Changes Made**:
|
|
|
|
- Added imports for `ModalService` and `ModalComponent`
|
|
- Added `ModalComponent` to component imports
|
|
- Injected `ModalService` in constructor
|
|
- Added example methods demonstrating modal usage:
|
|
- `showCustomModal()` - Shows 3-button custom dialog
|
|
- `showConfirmDialog()` - Shows Yes/No confirmation
|
|
- `showYesNoCancelDialog()` - Shows Yes/No/Cancel dialog
|
|
- `showInfoDialog()` - Shows information dialog
|
|
|
|
#### `src/frontend/src/app/root.component.html`
|
|
|
|
**Changes Made**:
|
|
|
|
- Added `<app-modal></app-modal>` component to template
|
|
- Added test buttons in form section to demonstrate modal functionality
|
|
- Test buttons include: Custom Modal, Confirm Dialog, Yes/No/Cancel, Info Dialog
|
|
|
|
### 3. Electron-Native Modal (Alternative)
|
|
|
|
To support invoking modals from the Electron main process with fully customizable styling, we added an alternative modal implementation which opens a dedicated `BrowserWindow` as a modal dialog.
|
|
|
|
#### New Files
|
|
|
|
- `src/main/modal.html`
|
|
- HTML/CSS/JS for a self-contained modal page
|
|
- Receives configuration over IPC (`custom-modal:config`)
|
|
- Renders title, message and up to 3 buttons
|
|
- Colors can be customized via CSS variables populated from config:
|
|
- background, text, buttonBg, buttonText, secondaryBg, secondaryText
|
|
- Each button can define its own inline style overrides via `buttonStyles` map
|
|
|
|
#### Changes in `src/main/main.js`
|
|
|
|
- Added `openCustomModalWindow(config)` helper to create a modal `BrowserWindow`
|
|
- Loads `modal.html` and sends the configuration after load
|
|
- Listens for `custom-modal:result` IPC to resolve the clicked button
|
|
- Exposed IPC handler `dialog:custom` to open the modal from renderer/preload
|
|
|
|
#### Changes in `src/preload/preload.js`
|
|
|
|
- Exposed `showNativeModal(config)` in `window.api` via `ipcRenderer.invoke('dialog:custom')`
|
|
|
|
#### Changes in `src/frontend/src/app/ipc.service.ts`
|
|
|
|
- Added wrapper method `showNativeModal(config)` to call the Electron-native modal from Angular code
|
|
|
|
#### Usage Example (from Angular renderer)
|
|
|
|
```ts
|
|
const result = await this.ipc.showNativeModal({
|
|
title: 'System Dialog',
|
|
message: 'Proceed with operation?',
|
|
buttons: [
|
|
{ id: 'yes', label: 'Yes', style: 'primary' },
|
|
{ id: 'no', label: 'No', style: 'secondary' },
|
|
{ id: 'cancel', label: 'Cancel', style: 'danger' }
|
|
],
|
|
colors: {
|
|
background: '#aa1c3a',
|
|
text: '#ffffff',
|
|
buttonBg: '#ffffff',
|
|
buttonText: '#aa1c3a',
|
|
secondaryBg: 'rgba(255,255,255,0.1)',
|
|
secondaryText: '#ffffff'
|
|
},
|
|
buttonStyles: {
|
|
yes: { bg: '#ffffff', text: '#aa1c3a' },
|
|
no: { bg: 'rgba(255,255,255,0.1)', text: '#ffffff' },
|
|
cancel: { bg: '#e53935', text: '#fff' }
|
|
}
|
|
});
|
|
// result => { buttonId: 'yes' | 'no' | 'cancel', buttonIndex: number, buttonLabel?: string }
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Basic Custom Modal
|
|
|
|
```typescript
|
|
const result = await this.modal.show({
|
|
title: 'Custom Dialog',
|
|
message: 'Choose an option:',
|
|
buttons: [
|
|
{ id: 'option1', label: 'Option 1', style: 'primary' },
|
|
{ id: 'option2', label: 'Option 2', style: 'secondary' },
|
|
{ id: 'cancel', label: 'Cancel', style: 'danger' }
|
|
]
|
|
});
|
|
console.log(`Clicked: ${result.buttonLabel} (ID: ${result.buttonId})`);
|
|
```
|
|
|
|
### Confirmation Dialog
|
|
|
|
```typescript
|
|
const confirmed = await this.modal.showConfirm(
|
|
'Delete Item',
|
|
'Are you sure you want to delete this item?'
|
|
);
|
|
if (confirmed) {
|
|
// Proceed with deletion
|
|
}
|
|
```
|
|
|
|
### Yes/No/Cancel Dialog
|
|
|
|
```typescript
|
|
const result = await this.modal.showYesNoCancel(
|
|
'Save Changes',
|
|
'Do you want to save your changes?'
|
|
);
|
|
switch (result) {
|
|
case 'yes': /* Save and continue */ break;
|
|
case 'no': /* Continue without saving */ break;
|
|
case 'cancel': /* Cancel operation */ break;
|
|
}
|
|
```
|
|
|
|
### Information Dialog
|
|
|
|
```typescript
|
|
await this.modal.showInfo(
|
|
'Success',
|
|
'Your changes have been saved successfully.'
|
|
);
|
|
```
|
|
|
|
## Button Styles
|
|
|
|
The modal supports three button styles:
|
|
|
|
1. **Primary** (`style: 'primary'`): White background, red text - matches footer buttons
|
|
2. **Secondary** (`style: 'secondary'`): Transparent background, white text
|
|
3. **Danger** (`style: 'danger'`): Red background, white text
|
|
|
|
## Styling Details
|
|
|
|
### Color Scheme
|
|
|
|
- **Background**: #aa1c3a (matches footer)
|
|
- **Text**: White (#ffffff)
|
|
- **Primary Buttons**: White background, red text
|
|
- **Secondary Buttons**: Transparent with white text
|
|
- **Danger Buttons**: Red background (#e53935)
|
|
|
|
### Layout
|
|
|
|
- Modal overlay covers entire screen
|
|
- Dialog is centered and responsive
|
|
- Maximum width: 500px
|
|
- Mobile-friendly with stacked buttons on small screens
|
|
|
|
## Integration Points
|
|
|
|
### Service Integration
|
|
|
|
The `ModalService` is provided at root level, making it available throughout the application:
|
|
|
|
```typescript
|
|
constructor(private modal: ModalService) {}
|
|
```
|
|
|
|
### Component Integration
|
|
|
|
The `ModalComponent` is imported in the main component and added to the template:
|
|
|
|
```html
|
|
<app-modal></app-modal>
|
|
```
|
|
|
|
## Testing
|
|
|
|
The implementation includes test buttons in the form section that demonstrate all modal types:
|
|
|
|
- Custom Modal: Shows 3-button dialog with different styles
|
|
- Confirm Dialog: Shows Yes/No confirmation
|
|
- Yes/No/Cancel: Shows 3-option dialog
|
|
- Info Dialog: Shows information with OK button
|
|
|
|
## Future Enhancements
|
|
|
|
Potential improvements could include:
|
|
|
|
1. Modal animations (fade in/out)
|
|
2. Keyboard navigation support
|
|
3. Escape key to close
|
|
4. Custom modal sizes
|
|
5. Modal stacking support
|
|
6. Form inputs within modals
|
|
7. Optional keyboard shortcuts (Enter/Esc)
|
|
8. Focus management and initial focus button
|
|
|
|
## Dependencies
|
|
|
|
The modal system requires:
|
|
|
|
- Angular CommonModule
|
|
- RxJS for reactive programming
|
|
- No external dependencies
|
|
|
|
## File Structure
|
|
|
|
``` еуче
|
|
src/frontend/src/app/
|
|
├── modal.service.ts # Service for modal management
|
|
├── modal.component.ts # Modal component
|
|
├── modal.component.scss # Modal styles
|
|
├── root.component.ts # Updated with modal integration
|
|
└── root.component.html # Updated with modal component
|
|
```
|
|
|
|
This implementation provides a complete, reusable modal dialog system that matches the application's design language and provides flexible configuration options for various dialog types.
|