@memberjunction/ng-explorer-settings 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,21 +1,67 @@
1
1
  # @memberjunction/ng-explorer-settings
2
2
 
3
- Angular components for managing MemberJunction application settings, including users, roles, applications, and entity permissions. This package provides a comprehensive administrative interface for configuring system access and permissions.
3
+ Angular components for the Settings section of MemberJunction Explorer. Provides a tabbed settings interface covering general preferences, user management, role management, application management, entity permissions, appearance, notifications, SQL logging, and profile settings.
4
4
 
5
5
  ## Overview
6
6
 
7
- The `@memberjunction/ng-explorer-settings` package provides a complete settings management interface for MemberJunction Explorer applications. It offers a unified navigation system with dedicated components for managing users, roles, applications, and entity permissions.
7
+ The `SettingsComponent` serves as the main container, registered via `@RegisterClass(BaseNavigationComponent, 'Settings')`. It provides a searchable, tabbed interface for administrative and user settings. Each settings area is implemented as a standalone component that can be used independently.
8
+
9
+ ```mermaid
10
+ graph TD
11
+ SC["SettingsComponent\n(<mj-settings>)"] --> GS["GeneralSettingsComponent"]
12
+ SC --> AI["AccountInfoComponent"]
13
+ SC --> AS["AppearanceSettingsComponent"]
14
+ SC --> APS["ApplicationSettingsComponent"]
15
+ SC --> UM["UserManagementComponent"]
16
+ SC --> RM["RoleManagementComponent"]
17
+ SC --> AM["ApplicationManagementComponent"]
18
+ SC --> EP["EntityPermissionsComponent"]
19
+ SC --> NP["NotificationPreferencesComponent"]
20
+ SC --> SL["SQLLoggingComponent"]
21
+ SC --> UP["UserProfileSettingsComponent"]
22
+ SC --> UAC["UserAppConfigComponent"]
23
+
24
+ UM --> UD["UserDialogComponent"]
25
+ RM --> RD["RoleDialogComponent"]
26
+ AM --> AD["ApplicationDialogComponent"]
27
+ EP --> PD["PermissionDialogComponent"]
28
+
29
+ style SC fill:#7c5295,stroke:#563a6b,color:#fff
30
+ style GS fill:#2d6a9f,stroke:#1a4971,color:#fff
31
+ style AI fill:#2d6a9f,stroke:#1a4971,color:#fff
32
+ style AS fill:#2d6a9f,stroke:#1a4971,color:#fff
33
+ style APS fill:#2d6a9f,stroke:#1a4971,color:#fff
34
+ style UM fill:#2d8659,stroke:#1a5c3a,color:#fff
35
+ style RM fill:#2d8659,stroke:#1a5c3a,color:#fff
36
+ style AM fill:#2d8659,stroke:#1a5c3a,color:#fff
37
+ style EP fill:#2d8659,stroke:#1a5c3a,color:#fff
38
+ style NP fill:#b8762f,stroke:#8a5722,color:#fff
39
+ style SL fill:#b8762f,stroke:#8a5722,color:#fff
40
+ style UP fill:#b8762f,stroke:#8a5722,color:#fff
41
+ style UAC fill:#b8762f,stroke:#8a5722,color:#fff
42
+ style UD fill:#2d8659,stroke:#1a5c3a,color:#fff
43
+ style RD fill:#2d8659,stroke:#1a5c3a,color:#fff
44
+ style AD fill:#2d8659,stroke:#1a5c3a,color:#fff
45
+ style PD fill:#2d8659,stroke:#1a5c3a,color:#fff
46
+ ```
8
47
 
9
48
  ## Features
10
49
 
11
- - **User Management**: Create, edit, activate/deactivate users with role assignments
12
- - **Role Management**: Define and manage security roles with user assignments
13
- - **Application Configuration**: Configure applications and their associated entities
14
- - **Entity Permissions**: Granular control over entity-level permissions
15
- - **SQL Logging Management**: Real-time SQL logging configuration and session control
16
- - **Transaction-based Updates**: Batch updates using MemberJunction's transaction system
17
- - **Responsive Navigation**: Left-side navigation with dynamic content area
18
- - **Real-time Updates**: Immediate reflection of permission and assignment changes
50
+ - **Tabbed settings interface** with search across all settings
51
+ - **General settings**: Core application preferences
52
+ - **Account info**: User account details
53
+ - **Appearance settings**: Theme and display preferences
54
+ - **Application settings**: Application-specific configuration
55
+ - **User management**: CRUD for users with dialog-based editing
56
+ - **Role management**: CRUD for roles with dialog-based editing
57
+ - **Application management**: CRUD for applications with dialog-based editing
58
+ - **Entity permissions**: Permission grid integrated from `@memberjunction/ng-entity-permissions`
59
+ - **Notification preferences**: Notification configuration
60
+ - **SQL logging**: SQL query logging viewer
61
+ - **User profile settings**: Profile editing
62
+ - **User app configuration**: Per-user application configuration
63
+ - **Reusable settings card**: `SettingsCardComponent` for consistent card layout
64
+ - **Shared settings module**: Common settings UI elements
19
65
 
20
66
  ## Installation
21
67
 
@@ -23,461 +69,63 @@ The `@memberjunction/ng-explorer-settings` package provides a complete settings
23
69
  npm install @memberjunction/ng-explorer-settings
24
70
  ```
25
71
 
26
- ## Usage
72
+ ## Key Dependencies
27
73
 
28
- ### Module Import
74
+ | Dependency | Purpose |
75
+ |---|---|
76
+ | `@memberjunction/core`, `@memberjunction/core-entities` | Entity metadata and data |
77
+ | `@memberjunction/ng-base-application` | BaseNavigationComponent |
78
+ | `@memberjunction/ng-entity-permissions` | Entity permission grid |
79
+ | `@memberjunction/ng-entity-form-dialog` | Entity form dialogs |
80
+ | `@memberjunction/ng-simple-record-list` | Simple record CRUD lists |
81
+ | `@memberjunction/ng-join-grid` | Join/relationship grid |
82
+ | `@memberjunction/ng-user-avatar` | User avatar display |
83
+ | `@progress/kendo-angular-*` | Kendo UI components |
84
+ | `@angular/cdk` | Angular CDK utilities |
29
85
 
30
- Import the `ExplorerSettingsModule` in your Angular application:
86
+ ## Usage
31
87
 
32
88
  ```typescript
33
89
  import { ExplorerSettingsModule } from '@memberjunction/ng-explorer-settings';
34
90
 
35
91
  @NgModule({
36
- imports: [
37
- CommonModule,
38
- ExplorerSettingsModule,
39
- // other imports...
40
- ]
92
+ imports: [ExplorerSettingsModule]
41
93
  })
42
- export class YourModule { }
43
- ```
44
-
45
- ### Basic Implementation
46
-
47
- Add the main settings component to your application:
48
-
49
- ```html
50
- <mj-settings></mj-settings>
51
- ```
52
-
53
- The component automatically handles routing to different settings sections based on the URL path.
54
-
55
- ## Components
56
-
57
- ### SettingsComponent
58
-
59
- The main navigation component that provides a consistent interface for all settings sections.
60
-
61
- **Selector**: `mj-settings`
62
-
63
- **Features**:
64
- - Left-side navigation menu
65
- - Dynamic content area based on selected section
66
- - URL-based routing support
67
- - Responsive layout using MemberJunction's container directives
68
-
69
- **Routes Handled**:
70
- - `/settings/users` - User list view
71
- - `/settings/user/:id` - Individual user details
72
- - `/settings/roles` - Role list view
73
- - `/settings/role/:id` - Individual role details
74
- - `/settings/applications` - Application list view
75
- - `/settings/application/:name` - Individual application details
76
- - `/settings/entitypermissions` - Entity permission management
77
- - `/settings/sqllogging` - SQL logging configuration and session management
78
-
79
- **Example**:
80
- ```typescript
81
- // Navigate to a specific user
82
- this.router.navigate(['/settings/user', userId]);
83
-
84
- // Navigate to roles section
85
- this.router.navigate(['/settings/roles']);
86
- ```
87
-
88
- ### SingleUserComponent
89
-
90
- Manages individual user details and configurations.
91
-
92
- **Selector**: `mj-single-user`
93
-
94
- **Inputs**:
95
- - `UserID: string` - The ID of the user to display/edit
96
-
97
- **Features**:
98
- - User information display and editing
99
- - User role assignments via embedded grid
100
- - User views management
101
- - Integration with entity form dialog for editing
102
-
103
- **Example**:
104
- ```html
105
- <mj-single-user [UserID]="selectedUserId"></mj-single-user>
106
- ```
107
-
108
- ### SingleRoleComponent
109
-
110
- Manages individual role details and user assignments.
111
-
112
- **Selector**: `mj-single-role`
113
-
114
- **Inputs**:
115
- - `RoleID: string` - The ID of the role to display/edit
116
-
117
- **Features**:
118
- - Role information display and editing
119
- - User assignments to the role
120
- - Batch operations for user-role assignments
121
-
122
- **Example**:
123
- ```html
124
- <mj-single-role [RoleID]="selectedRoleId"></mj-single-role>
125
- ```
126
-
127
- ### SingleApplicationComponent
128
-
129
- Manages application configurations and entity associations.
130
-
131
- **Selector**: `mj-single-application`
132
-
133
- **Inputs**:
134
- - `ApplicationID: string` - The ID of the application to manage
135
-
136
- **Features**:
137
- - Application details management
138
- - Entity associations configuration
139
- - Bulk entity assignment operations
140
-
141
- **Example**:
142
- ```html
143
- <mj-single-application [ApplicationID]="selectedApplicationId"></mj-single-application>
144
- ```
145
-
146
- ### UserRolesGridComponent
147
-
148
- A specialized grid for managing user-role relationships.
149
-
150
- **Selector**: `mj-user-roles-grid`
151
-
152
- **Inputs**:
153
- - `UserID: string` - User ID when in 'Users' mode
154
- - `RoleID: string` - Role ID when in 'Roles' mode
155
- - `Mode: 'Users' | 'Roles'` - Determines the grid's perspective
156
- - `UserRecord: UserEntity | null` - User entity when in 'Users' mode
157
- - `RoleRecord: RoleEntity | null` - Role entity when in 'Roles' mode
158
-
159
- **Features**:
160
- - Checkbox-based role/user selection
161
- - Batch save/cancel operations
162
- - Flip all functionality
163
- - Transaction-based updates
164
- - Visual indication of pending changes
165
-
166
- **Example**:
167
- ```html
168
- <!-- For managing roles assigned to a user -->
169
- <mj-user-roles-grid
170
- [UserID]="userId"
171
- [UserRecord]="userEntity"
172
- Mode="Users">
173
- </mj-user-roles-grid>
174
-
175
- <!-- For managing users assigned to a role -->
176
- <mj-user-roles-grid
177
- [RoleID]="roleId"
178
- [RoleRecord]="roleEntity"
179
- Mode="Roles">
180
- </mj-user-roles-grid>
181
- ```
182
-
183
- ### ApplicationEntitiesGridComponent
184
-
185
- Manages entity associations with applications.
186
-
187
- **Selector**: `mj-application-entities-grid`
188
-
189
- **Inputs**:
190
- - `ApplicationID: string` - Application ID when in 'Applications' mode
191
- - `EntityID: string` - Entity ID when in 'Entities' mode
192
- - `Mode: 'Applications' | 'Entities'` - Determines the grid's perspective
193
- - `ApplicationRecord: ApplicationEntity | null` - Application entity
194
- - `EntityRecord: EntityEntity | null` - Entity record
195
-
196
- **Features**:
197
- - Entity-application association management
198
- - Bulk selection/deselection
199
- - Transaction-based saves
200
- - Dirty state tracking
201
-
202
- **Example**:
203
- ```html
204
- <mj-application-entities-grid
205
- [ApplicationID]="appId"
206
- [ApplicationRecord]="appEntity"
207
- Mode="Applications">
208
- </mj-application-entities-grid>
209
- ```
210
-
211
- ### SqlLoggingComponent
212
-
213
- Provides comprehensive SQL logging management for debugging and migration generation.
214
-
215
- **Selector**: `mj-sql-logging`
216
-
217
- **Features**:
218
- - Real-time SQL logging session management
219
- - Owner-level access control (requires `Type = 'Owner'`)
220
- - Session configuration with filtering options
221
- - Live session monitoring with statement counts
222
- - Multiple concurrent session support
223
- - Auto-refresh capabilities
224
- - Integration with MemberJunction's GraphQL API
225
-
226
- **Key Capabilities**:
227
- - **Session Creation**: Start new SQL logging sessions with custom options
228
- - **User Filtering**: Capture SQL statements from specific users only
229
- - **Format Options**: Standard SQL logs or migration-ready files
230
- - **Real-time Monitoring**: View active sessions and their progress
231
- - **Batch Operations**: Stop individual sessions or all sessions at once
232
- - **Auto-cleanup**: Sessions automatically expire and clean up empty files
233
-
234
- **Security Requirements**:
235
- - User must have `Type = 'Owner'` in the Users table
236
- - SQL logging must be enabled in server configuration
237
- - Valid authentication required for all operations
238
-
239
- **Example Usage**:
240
- ```html
241
- <!-- Include in settings navigation -->
242
- <mj-sql-logging></mj-sql-logging>
243
- ```
244
-
245
- **Session Configuration Options**:
246
- ```typescript
247
- interface SessionOptions {
248
- fileName?: string; // Custom log file name
249
- sessionName?: string; // Human-readable session name
250
- filterToCurrentUser?: boolean; // Filter to current user's SQL only
251
- formatAsMigration?: boolean; // Format as migration file
252
- prettyPrint?: boolean; // Format SQL with indentation
253
- statementTypes?: 'queries' | 'mutations' | 'both'; // SQL types to capture
254
- }
255
- ```
256
-
257
- **GraphQL Integration**:
258
- ```typescript
259
- // The component automatically handles GraphQL operations:
260
- // - sqlLoggingConfig: Get current configuration
261
- // - activeSqlLoggingSessions: List active sessions
262
- // - startSqlLogging: Create new session
263
- // - stopSqlLogging: Stop specific session
264
- // - stopAllSqlLogging: Stop all sessions
265
- ```
266
-
267
- **UI Features**:
268
- - **Dashboard-style interface** with modern AI dashboard styling
269
- - **Status indicators** showing configuration state and active sessions
270
- - **Interactive session cards** with duration, statement counts, and controls
271
- - **Dialog-based session creation** with comprehensive options
272
- - **Auto-refresh toggle** for real-time session monitoring
273
- - **Responsive layout** optimized for desktop use
274
-
275
- **Access Control**:
276
- - Non-Owner users see access denied message with permission refresh option
277
- - Disabled state shown when SQL logging not enabled in server config
278
- - Clear instructions provided for enabling SQL logging
279
-
280
- **Error Handling**:
281
- - Comprehensive error messages for common issues
282
- - Graceful handling of permission and configuration problems
283
- - User-friendly notifications for all operations
284
- - Debug logging for troubleshooting
285
-
286
- **Integration Notes**:
287
- - Requires MJServer with SqlLoggingConfigResolver
288
- - Works with SQLServerDataProvider logging capabilities
289
- - Follows MemberJunction's security and styling patterns
290
- - Compatible with modern Angular control flow syntax (`@if`, `@for`)
291
-
292
- ## User Management Features
293
-
294
- ### User Activation/Deactivation
295
-
296
- The settings module implements a soft-delete pattern for users:
297
-
298
- ```typescript
299
- // Example implementation in SettingsComponent
300
- public async toggleUserActivation(record: BaseEntity) {
301
- try {
302
- const user = record as UserEntity;
303
- const currentlyActive = user.IsActive;
304
-
305
- // Toggle the IsActive flag
306
- user.IsActive = !currentlyActive;
307
-
308
- if (await user.Save()) {
309
- MJNotificationService.Instance.CreateSimpleNotification(
310
- `User ${user.Name} has been ${currentlyActive ? 'deactivated' : 'activated'} successfully.`,
311
- 'success',
312
- 3000
313
- );
314
- }
315
- } catch (error) {
316
- console.error('Error toggling user activation:', error);
317
- MJNotificationService.Instance.CreateSimpleNotification(
318
- 'An error occurred while toggling user activation.',
319
- 'error',
320
- 5000
321
- );
322
- }
323
- }
324
- ```
325
-
326
- ### Custom Action Support
327
-
328
- The user list supports custom actions with configurable icons and tooltips:
329
-
330
- ```typescript
331
- // Icon function for toggle button
332
- public getUserToggleIcon(record: BaseEntity): string {
333
- const user = record as UserEntity;
334
- return user.IsActive ? 'fa-user-lock' : 'fa-user-check';
335
- }
336
-
337
- // Tooltip function for toggle button
338
- public getUserToggleTooltip(record: BaseEntity): string {
339
- const user = record as UserEntity;
340
- return user.IsActive ? 'Deactivate user' : 'Activate user';
341
- }
342
- ```
343
-
344
- ## Configuration Options
345
-
346
- ### Navigation Options
347
-
348
- The settings component defines navigation options:
349
-
350
- ```typescript
351
- public options = [
352
- { label: 'Users', value: SettingsItem.Users },
353
- { label: 'Roles', value: SettingsItem.Roles },
354
- { label: 'Applications', value: SettingsItem.Applications },
355
- { label: 'Entity Permissions', value: SettingsItem.EntityPermissions },
356
- { label: 'SQL Logging', value: SettingsItem.SqlLogging }
357
- ];
358
- ```
359
-
360
- ### Grid Configuration
361
-
362
- User roles and application entities grids support various configurations:
363
-
364
- ```typescript
365
- // Example: Configure grid height
366
- <mj-user-roles-grid
367
- [UserID]="userId"
368
- style="height: 600px;">
369
- </mj-user-roles-grid>
370
- ```
371
-
372
- ## Dependencies
373
-
374
- This package depends on several MemberJunction and third-party packages:
375
-
376
- ### MemberJunction Dependencies
377
- - `@memberjunction/core`: Core functionality and metadata
378
- - `@memberjunction/core-entities`: Entity definitions
379
- - `@memberjunction/global`: Global utilities and decorators
380
- - `@memberjunction/ng-container-directives`: Layout directives
381
- - `@memberjunction/ng-shared`: Shared Angular components
382
- - `@memberjunction/ng-notifications`: Notification service
383
- - `@memberjunction/ng-entity-permissions`: Entity permission components
384
- - `@memberjunction/ng-base-forms`: Base form components
385
- - `@memberjunction/ng-entity-form-dialog`: Entity editing dialogs
386
- - `@memberjunction/ng-user-view-grid`: User view grid component
387
- - `@memberjunction/ng-simple-record-list`: Record list component
388
- - `@memberjunction/ng-tabstrip`: Tab navigation component
389
- - `@memberjunction/graphql-dataprovider`: GraphQL operations for SQL logging
390
-
391
- ### Kendo UI Dependencies
392
- - `@progress/kendo-angular-dropdowns`: Dropdown components
393
- - `@progress/kendo-angular-grid`: Grid functionality
394
- - `@progress/kendo-angular-buttons`: Button components
395
- - `@progress/kendo-angular-dialog`: Dialog components
396
- - `@progress/kendo-angular-layout`: Layout utilities
397
- - `@progress/kendo-angular-indicators`: Loading indicators
398
- - `@progress/kendo-angular-inputs`: Form input components
399
- - `@progress/kendo-angular-label`: Label components
400
- - `@progress/kendo-angular-dialog`: Modal dialogs for session configuration
401
-
402
- ### Angular Dependencies (Peer)
403
- - `@angular/common`: ^18.0.2
404
- - `@angular/core`: ^18.0.2
405
- - `@angular/forms`: ^18.0.2
406
- - `@angular/router`: ^18.0.2
407
-
408
- ## Integration with MemberJunction
409
-
410
- ### Entity Registration
411
-
412
- Components register with MemberJunction's class system:
413
-
414
- ```typescript
415
- @RegisterClass(BaseNavigationComponent, 'Settings')
416
- export class SettingsComponent extends BaseNavigationComponent {
417
- // Component implementation
418
- }
419
- ```
420
-
421
- ### Transaction Support
422
-
423
- Batch operations use MemberJunction's transaction system:
424
-
425
- ```typescript
426
- const md = new Metadata();
427
- const tg = await md.CreateTransactionGroup();
428
-
429
- for (const record of records) {
430
- record.TransactionGroup = tg;
431
- await record.Save();
432
- }
433
-
434
- await tg.Submit();
435
- ```
436
-
437
- ### Metadata Integration
438
-
439
- Components leverage MemberJunction's metadata system:
440
-
441
- ```typescript
442
- const md = new Metadata();
443
- const userEntity = await md.GetEntityObject<UserEntity>('Users');
444
- const applications = md.Applications;
445
- const roles = md.Roles;
446
- ```
447
-
448
- ## Build and Development
449
-
450
- ### Building the Package
94
+ export class AppModule {}
95
+ ```
96
+
97
+ The `SettingsComponent` is registered via `@RegisterClass(BaseNavigationComponent, 'Settings')` and is typically loaded through Explorer's navigation system.
98
+
99
+ ## Exported API
100
+
101
+ | Export | Type | Description |
102
+ |---|---|---|
103
+ | `ExplorerSettingsModule` | NgModule | Main settings module |
104
+ | `SettingsComponent` | Component | Main tabbed settings container |
105
+ | `GeneralSettingsComponent` | Component | General preferences |
106
+ | `AccountInfoComponent` | Component | Account information |
107
+ | `AppearanceSettingsComponent` | Component | Theme/display settings |
108
+ | `ApplicationSettingsComponent` | Component | Application preferences |
109
+ | `UserManagementComponent` | Component | User CRUD management |
110
+ | `RoleManagementComponent` | Component | Role CRUD management |
111
+ | `ApplicationManagementComponent` | Component | Application CRUD management |
112
+ | `EntityPermissionsSettingsComponent` | Component | Entity permission management |
113
+ | `NotificationPreferencesComponent` | Component | Notification settings |
114
+ | `SQLLoggingComponent` | Component | SQL logging viewer |
115
+ | `UserProfileSettingsComponent` | Component | Profile editing |
116
+ | `UserAppConfigComponent` | Component | User app configuration |
117
+ | `SettingsCardComponent` | Component | Reusable settings card layout |
118
+ | `UserDialogComponent` | Component | User edit dialog |
119
+ | `RoleDialogComponent` | Component | Role edit dialog |
120
+ | `ApplicationDialogComponent` | Component | Application edit dialog |
121
+ | `PermissionDialogComponent` | Component | Permission edit dialog |
122
+
123
+ ## Build
451
124
 
452
125
  ```bash
453
- # From the package directory
454
- npm run build
455
-
456
- # Or from the repository root
457
- npm run build -- --filter="@memberjunction/ng-explorer-settings"
126
+ cd packages/Angular/Explorer/explorer-settings && npm run build
458
127
  ```
459
128
 
460
- ### TypeScript Configuration
461
-
462
- The package uses strict TypeScript settings:
463
- - Target: ES2015
464
- - Module: ES2020
465
- - Strict mode enabled
466
- - Source maps generated
467
- - Declaration files generated
468
-
469
- ## Best Practices
470
-
471
- 1. **Always use transactions** for batch operations to ensure data consistency
472
- 2. **Leverage entity metadata** instead of hardcoding entity names
473
- 3. **Use the provided navigation methods** for consistent routing behavior
474
- 4. **Handle errors appropriately** with user-friendly notifications
475
- 5. **Follow MemberJunction patterns** for entity instantiation and data loading
476
-
477
- ## Version
478
-
479
- Current version: 2.43.0
480
-
481
129
  ## License
482
130
 
483
- ISC
131
+ ISC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-explorer-settings",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "MemberJunction: Reusable Angular components for the settings section of the MJ Explorer App",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -25,23 +25,23 @@
25
25
  "@angular/router": "21.1.3"
26
26
  },
27
27
  "dependencies": {
28
- "@memberjunction/core": "4.0.0",
29
- "@memberjunction/core-entities": "4.0.0",
30
- "@memberjunction/global": "4.0.0",
31
- "@memberjunction/graphql-dataprovider": "4.0.0",
32
- "@memberjunction/ng-base-application": "4.0.0",
33
- "@memberjunction/ng-base-forms": "4.0.0",
34
- "@memberjunction/ng-code-editor": "4.0.0",
35
- "@memberjunction/ng-container-directives": "4.0.0",
36
- "@memberjunction/ng-entity-form-dialog": "4.0.0",
37
- "@memberjunction/ng-entity-permissions": "4.0.0",
38
- "@memberjunction/ng-join-grid": "4.0.0",
39
- "@memberjunction/ng-notifications": "4.0.0",
40
- "@memberjunction/ng-shared": "4.0.0",
41
- "@memberjunction/ng-shared-generic": "4.0.0",
42
- "@memberjunction/ng-simple-record-list": "4.0.0",
43
- "@memberjunction/ng-tabstrip": "4.0.0",
44
- "@memberjunction/ng-user-avatar": "4.0.0",
28
+ "@memberjunction/core": "4.1.0",
29
+ "@memberjunction/core-entities": "4.1.0",
30
+ "@memberjunction/global": "4.1.0",
31
+ "@memberjunction/graphql-dataprovider": "4.1.0",
32
+ "@memberjunction/ng-base-application": "4.1.0",
33
+ "@memberjunction/ng-base-forms": "4.1.0",
34
+ "@memberjunction/ng-code-editor": "4.1.0",
35
+ "@memberjunction/ng-container-directives": "4.1.0",
36
+ "@memberjunction/ng-entity-form-dialog": "4.1.0",
37
+ "@memberjunction/ng-entity-permissions": "4.1.0",
38
+ "@memberjunction/ng-join-grid": "4.1.0",
39
+ "@memberjunction/ng-notifications": "4.1.0",
40
+ "@memberjunction/ng-shared": "4.1.0",
41
+ "@memberjunction/ng-shared-generic": "4.1.0",
42
+ "@memberjunction/ng-simple-record-list": "4.1.0",
43
+ "@memberjunction/ng-tabstrip": "4.1.0",
44
+ "@memberjunction/ng-user-avatar": "4.1.0",
45
45
  "@progress/kendo-angular-buttons": "22.0.1",
46
46
  "@progress/kendo-angular-dialog": "22.0.1",
47
47
  "@progress/kendo-angular-dropdowns": "22.0.1",
@@ -1,27 +0,0 @@
1
- import { TemplateRef } from '@angular/core';
2
- import * as i0 from "@angular/core";
3
- /**
4
- * A reusable settings card component providing consistent styling and layout
5
- * across all settings sections. Follows the modern AI dashboard design patterns.
6
- */
7
- export declare class SettingsCardComponent {
8
- /** Card title displayed in the header */
9
- title?: string;
10
- /** Card subtitle displayed below the title */
11
- subtitle?: string;
12
- /** Whether to use floating card style (higher elevation) */
13
- floating: boolean;
14
- /** Card size variant */
15
- size: 'sm' | 'md' | 'lg';
16
- /** Whether to remove padding from content area */
17
- noPadding: boolean;
18
- /** Template for custom header content */
19
- headerTemplate?: TemplateRef<any>;
20
- /** Template for header action buttons */
21
- actionTemplate?: TemplateRef<any>;
22
- /** Template for footer content */
23
- footerTemplate?: TemplateRef<any>;
24
- static ɵfac: i0.ɵɵFactoryDeclaration<SettingsCardComponent, never>;
25
- static ɵcmp: i0.ɵɵComponentDeclaration<SettingsCardComponent, "mj-settings-card", never, { "title": { "alias": "title"; "required": false; }; "subtitle": { "alias": "subtitle"; "required": false; }; "floating": { "alias": "floating"; "required": false; }; "size": { "alias": "size"; "required": false; }; "noPadding": { "alias": "noPadding"; "required": false; }; "headerTemplate": { "alias": "headerTemplate"; "required": false; }; "actionTemplate": { "alias": "actionTemplate"; "required": false; }; "footerTemplate": { "alias": "footerTemplate"; "required": false; }; }, {}, never, ["*"], true, never>;
26
- }
27
- //# sourceMappingURL=settings-card.component.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings-card.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/shared/components/settings-card/settings-card.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,WAAW,EAAE,MAAM,eAAe,CAAC;;AAG9D;;;GAGG;AACH,qBA0Ca,qBAAqB;IAChC,yCAAyC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,8CAA8C;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,4DAA4D;IACnD,QAAQ,UAAS;IAE1B,wBAAwB;IACf,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAQ;IAEzC,kDAAkD;IACzC,SAAS,UAAS;IAE3B,yCAAyC;IAChC,cAAc,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAE3C,yCAAyC;IAChC,cAAc,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAE3C,kCAAkC;IACzB,cAAc,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;yCAvBhC,qBAAqB;2CAArB,qBAAqB;CAwBjC"}
@@ -1,170 +0,0 @@
1
- import { Component, Input } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import * as i0 from "@angular/core";
4
- import * as i1 from "@angular/common";
5
- const _c0 = ["*"];
6
- function SettingsCardComponent_Conditional_1_Conditional_1_ng_container_0_Template(rf, ctx) { if (rf & 1) {
7
- i0.ɵɵelementContainer(0);
8
- } }
9
- function SettingsCardComponent_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
10
- i0.ɵɵtemplate(0, SettingsCardComponent_Conditional_1_Conditional_1_ng_container_0_Template, 1, 0, "ng-container", 4);
11
- } if (rf & 2) {
12
- const ctx_r0 = i0.ɵɵnextContext(2);
13
- i0.ɵɵproperty("ngTemplateOutlet", ctx_r0.headerTemplate);
14
- } }
15
- function SettingsCardComponent_Conditional_1_Conditional_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
16
- i0.ɵɵelementStart(0, "p", 7);
17
- i0.ɵɵtext(1);
18
- i0.ɵɵelementEnd();
19
- } if (rf & 2) {
20
- const ctx_r0 = i0.ɵɵnextContext(3);
21
- i0.ɵɵadvance();
22
- i0.ɵɵtextInterpolate(ctx_r0.subtitle);
23
- } }
24
- function SettingsCardComponent_Conditional_1_Conditional_2_Conditional_4_ng_container_1_Template(rf, ctx) { if (rf & 1) {
25
- i0.ɵɵelementContainer(0);
26
- } }
27
- function SettingsCardComponent_Conditional_1_Conditional_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
28
- i0.ɵɵelementStart(0, "div", 8);
29
- i0.ɵɵtemplate(1, SettingsCardComponent_Conditional_1_Conditional_2_Conditional_4_ng_container_1_Template, 1, 0, "ng-container", 4);
30
- i0.ɵɵelementEnd();
31
- } if (rf & 2) {
32
- const ctx_r0 = i0.ɵɵnextContext(3);
33
- i0.ɵɵadvance();
34
- i0.ɵɵproperty("ngTemplateOutlet", ctx_r0.actionTemplate);
35
- } }
36
- function SettingsCardComponent_Conditional_1_Conditional_2_Template(rf, ctx) { if (rf & 1) {
37
- i0.ɵɵelementStart(0, "div", 5)(1, "h3", 6);
38
- i0.ɵɵtext(2);
39
- i0.ɵɵelementEnd();
40
- i0.ɵɵtemplate(3, SettingsCardComponent_Conditional_1_Conditional_2_Conditional_3_Template, 2, 1, "p", 7);
41
- i0.ɵɵelementEnd();
42
- i0.ɵɵtemplate(4, SettingsCardComponent_Conditional_1_Conditional_2_Conditional_4_Template, 2, 1, "div", 8);
43
- } if (rf & 2) {
44
- const ctx_r0 = i0.ɵɵnextContext(2);
45
- i0.ɵɵadvance(2);
46
- i0.ɵɵtextInterpolate(ctx_r0.title);
47
- i0.ɵɵadvance();
48
- i0.ɵɵconditional(ctx_r0.subtitle ? 3 : -1);
49
- i0.ɵɵadvance();
50
- i0.ɵɵconditional(ctx_r0.actionTemplate ? 4 : -1);
51
- } }
52
- function SettingsCardComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
53
- i0.ɵɵelementStart(0, "div", 1);
54
- i0.ɵɵtemplate(1, SettingsCardComponent_Conditional_1_Conditional_1_Template, 1, 1, "ng-container")(2, SettingsCardComponent_Conditional_1_Conditional_2_Template, 5, 3);
55
- i0.ɵɵelementEnd();
56
- } if (rf & 2) {
57
- const ctx_r0 = i0.ɵɵnextContext();
58
- i0.ɵɵadvance();
59
- i0.ɵɵconditional(ctx_r0.headerTemplate ? 1 : 2);
60
- } }
61
- function SettingsCardComponent_Conditional_4_ng_container_1_Template(rf, ctx) { if (rf & 1) {
62
- i0.ɵɵelementContainer(0);
63
- } }
64
- function SettingsCardComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
65
- i0.ɵɵelementStart(0, "div", 3);
66
- i0.ɵɵtemplate(1, SettingsCardComponent_Conditional_4_ng_container_1_Template, 1, 0, "ng-container", 4);
67
- i0.ɵɵelementEnd();
68
- } if (rf & 2) {
69
- const ctx_r0 = i0.ɵɵnextContext();
70
- i0.ɵɵadvance();
71
- i0.ɵɵproperty("ngTemplateOutlet", ctx_r0.footerTemplate);
72
- } }
73
- /**
74
- * A reusable settings card component providing consistent styling and layout
75
- * across all settings sections. Follows the modern AI dashboard design patterns.
76
- */
77
- export class SettingsCardComponent {
78
- /** Card title displayed in the header */
79
- title;
80
- /** Card subtitle displayed below the title */
81
- subtitle;
82
- /** Whether to use floating card style (higher elevation) */
83
- floating = false;
84
- /** Card size variant */
85
- size = 'md';
86
- /** Whether to remove padding from content area */
87
- noPadding = false;
88
- /** Template for custom header content */
89
- headerTemplate;
90
- /** Template for header action buttons */
91
- actionTemplate;
92
- /** Template for footer content */
93
- footerTemplate;
94
- static ɵfac = function SettingsCardComponent_Factory(t) { return new (t || SettingsCardComponent)(); };
95
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsCardComponent, selectors: [["mj-settings-card"]], inputs: { title: "title", subtitle: "subtitle", floating: "floating", size: "size", noPadding: "noPadding", headerTemplate: "headerTemplate", actionTemplate: "actionTemplate", footerTemplate: "footerTemplate" }, standalone: true, features: [i0.ɵɵStandaloneFeature], ngContentSelectors: _c0, decls: 5, vars: 10, consts: [[1, "mj-card"], [1, "mj-card-header"], [1, "mj-card-body"], [1, "mj-card-footer"], [4, "ngTemplateOutlet"], [1, "header-content"], [1, "card-title"], [1, "card-subtitle"], [1, "mj-card-actions"]], template: function SettingsCardComponent_Template(rf, ctx) { if (rf & 1) {
96
- i0.ɵɵprojectionDef();
97
- i0.ɵɵelementStart(0, "div", 0);
98
- i0.ɵɵtemplate(1, SettingsCardComponent_Conditional_1_Template, 3, 1, "div", 1);
99
- i0.ɵɵelementStart(2, "div", 2);
100
- i0.ɵɵprojection(3);
101
- i0.ɵɵelementEnd();
102
- i0.ɵɵtemplate(4, SettingsCardComponent_Conditional_4_Template, 2, 1, "div", 3);
103
- i0.ɵɵelementEnd();
104
- } if (rf & 2) {
105
- i0.ɵɵclassProp("mj-card-floating", ctx.floating)("mj-card-sm", ctx.size === "sm")("mj-card-lg", ctx.size === "lg");
106
- i0.ɵɵadvance();
107
- i0.ɵɵconditional(ctx.title || ctx.headerTemplate ? 1 : -1);
108
- i0.ɵɵadvance();
109
- i0.ɵɵclassProp("no-padding", ctx.noPadding);
110
- i0.ɵɵadvance(2);
111
- i0.ɵɵconditional(ctx.footerTemplate ? 4 : -1);
112
- } }, dependencies: [CommonModule, i1.NgTemplateOutlet], styles: ["@keyframes _ngcontent-%COMP%_shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n[_nghost-%COMP%] {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n font-size: 14px;\n line-height: 1.4;\n color: #212121;\n}\n[_nghost-%COMP%] *[_ngcontent-%COMP%] {\n box-sizing: border-box;\n}\n\n.settings-card[_ngcontent-%COMP%] {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n padding: 20px;\n}\n.settings-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n\n.settings-card-floating[_ngcontent-%COMP%] {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n padding: 20px;\n}\n.settings-card-floating[_ngcontent-%COMP%]:hover {\n box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-2px);\n}\n\n.settings-card-sm[_ngcontent-%COMP%] {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n padding: 16px;\n}\n.settings-card-sm[_ngcontent-%COMP%]:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n\n.settings-card-lg[_ngcontent-%COMP%] {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n padding: 24px;\n}\n.settings-card-lg[_ngcontent-%COMP%]:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n\n.dashboard-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding: 24px 0 16px 0;\n}\n.dashboard-header[_ngcontent-%COMP%] .header-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n.dashboard-header[_ngcontent-%COMP%] .header-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], .dashboard-header[_ngcontent-%COMP%] .header-info[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .dashboard-header[_ngcontent-%COMP%] .header-info[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-weight: 600;\n color: #212121;\n font-size: 24px;\n line-height: 1.2;\n}\n.dashboard-header[_ngcontent-%COMP%] .header-info[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n.dashboard-header[_ngcontent-%COMP%] .header-info[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n.dashboard-header[_ngcontent-%COMP%] .header-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid #e0e0e0;\n}\n.section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .section-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-weight: 500;\n color: #212121;\n font-size: 16px;\n}\n.section-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.control-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #ffffff;\n color: #212121;\n border-color: #bdbdbd;\n}\n.control-btn[_ngcontent-%COMP%]:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.control-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #f8f9fa;\n border-color: #2196f3;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n.control-btn.control-btn-primary[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #2196f3;\n color: #ffffff;\n border-color: #2196f3;\n}\n.control-btn.control-btn-primary[_ngcontent-%COMP%]:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn.control-btn-primary[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn.control-btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.control-btn.control-btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #1976d2;\n border-color: #1976d2;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.2);\n transform: translateY(-1px);\n}\n.control-btn.control-btn-primary[_ngcontent-%COMP%]:active {\n transform: translateY(0);\n}\n.control-btn.control-btn-danger[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #f44336;\n color: #ffffff;\n border-color: #f44336;\n}\n.control-btn.control-btn-danger[_ngcontent-%COMP%]:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn.control-btn-danger[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn.control-btn-danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.control-btn.control-btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #ea1c0d;\n border-color: #ea1c0d;\n box-shadow: 0 2px 8px rgba(244, 67, 54, 0.3);\n transform: translateY(-1px);\n}\n.control-btn.control-btn-ghost[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: transparent;\n color: #666666;\n border-color: transparent;\n}\n.control-btn.control-btn-ghost[_ngcontent-%COMP%]:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn.control-btn-ghost[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn.control-btn-ghost[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.control-btn.control-btn-ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #f8f9fa;\n color: #2196f3;\n}\n.control-btn.control-btn-sm[_ngcontent-%COMP%] {\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n}\n.control-btn.control-btn-sm[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n.control-btn.control-btn-lg[_ngcontent-%COMP%] {\n height: 44px;\n padding: 0 24px;\n font-size: 14px;\n}\n.control-btn.control-btn-lg[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: transparent;\n color: #666666;\n border-color: transparent;\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n width: 28px;\n padding: 0;\n}\n.action-btn[_ngcontent-%COMP%]:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.action-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #f8f9fa;\n color: #2196f3;\n}\n.action-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n.action-btn.action-btn-primary[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #2196f3;\n color: #ffffff;\n border-color: #2196f3;\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n width: 28px;\n padding: 0;\n}\n.action-btn.action-btn-primary[_ngcontent-%COMP%]:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.action-btn.action-btn-primary[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.action-btn.action-btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.action-btn.action-btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #1976d2;\n border-color: #1976d2;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.2);\n transform: translateY(-1px);\n}\n.action-btn.action-btn-primary[_ngcontent-%COMP%]:active {\n transform: translateY(0);\n}\n.action-btn.action-btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n.action-btn.action-btn-danger[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #f44336;\n color: #ffffff;\n border-color: #f44336;\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n width: 28px;\n padding: 0;\n}\n.action-btn.action-btn-danger[_ngcontent-%COMP%]:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.action-btn.action-btn-danger[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.action-btn.action-btn-danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.action-btn.action-btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #ea1c0d;\n border-color: #ea1c0d;\n box-shadow: 0 2px 8px rgba(244, 67, 54, 0.3);\n transform: translateY(-1px);\n}\n.action-btn.action-btn-danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.info-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(33, 150, 243, 0.1);\n color: #1976d2;\n border: 1px solid rgba(33, 150, 243, 0.2);\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(158, 158, 158, 0.1);\n color: #666666;\n border: 1px solid rgba(158, 158, 158, 0.2);\n}\n.status-badge.status-active[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(76, 175, 80, 0.1);\n color: #3d8b40;\n border: 1px solid rgba(76, 175, 80, 0.2);\n}\n.status-badge.status-migration[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(33, 150, 243, 0.1);\n color: #1976d2;\n border: 1px solid rgba(33, 150, 243, 0.2);\n}\n.status-badge.status-warning[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(255, 193, 7, 0.1);\n color: #6d5200;\n border: 1px solid rgba(255, 193, 7, 0.2);\n}\n.status-badge.status-error[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(244, 67, 54, 0.1);\n color: #ea1c0d;\n border: 1px solid rgba(244, 67, 54, 0.2);\n}\n\n.settings-nav[_ngcontent-%COMP%] {\n width: 220px;\n min-width: 220px;\n max-width: 220px;\n background: #ffffff;\n border-right: 1px solid #e0e0e0;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow-y: auto;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n.settings-nav[_ngcontent-%COMP%] .nav-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n margin: 0 8px 4px 8px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 400;\n color: #666666;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n position: relative;\n}\n.settings-nav[_ngcontent-%COMP%] .nav-item[_ngcontent-%COMP%]::before {\n content: \"\";\n position: absolute;\n left: 0;\n top: 50%;\n transform: translateY(-50%);\n width: 3px;\n height: 0;\n background: #2196f3;\n border-radius: 0 2px 2px 0;\n transition: height all 0.15s ease;\n}\n.settings-nav[_ngcontent-%COMP%] .nav-item[_ngcontent-%COMP%]:hover {\n background: #f8f9fa;\n color: #2196f3;\n transform: translateX(2px);\n}\n.settings-nav[_ngcontent-%COMP%] .nav-item.active[_ngcontent-%COMP%] {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n font-weight: 500;\n}\n.settings-nav[_ngcontent-%COMP%] .nav-item.active[_ngcontent-%COMP%]::before {\n height: 24px;\n}\n.settings-nav[_ngcontent-%COMP%] .nav-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n width: 18px;\n text-align: center;\n}\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n.form-field[_ngcontent-%COMP%] .field-label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 4px;\n font-size: 12px;\n font-weight: 500;\n color: #212121;\n}\n.form-field[_ngcontent-%COMP%] .field-hint[_ngcontent-%COMP%] {\n margin-top: 4px;\n font-size: 11px;\n color: #9e9e9e;\n}\n.form-field[_ngcontent-%COMP%] .field-error[_ngcontent-%COMP%] {\n margin-top: 4px;\n font-size: 11px;\n color: #f44336;\n}\n.form-field[_ngcontent-%COMP%] input[_ngcontent-%COMP%], .form-field[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%], .form-field[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n width: 100%;\n height: 36px;\n padding: 0 8px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 12px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n background: #ffffff;\n color: #212121;\n transition: all 0.15s ease;\n outline: none;\n}\n.form-field[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder, .form-field[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%]::placeholder, .form-field[_ngcontent-%COMP%] select[_ngcontent-%COMP%]::placeholder {\n color: #9e9e9e;\n}\n.form-field[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus, .form-field[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%]:focus, .form-field[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:focus {\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.2);\n}\n.form-field[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:disabled, .form-field[_ngcontent-%COMP%] textarea[_ngcontent-%COMP%]:disabled, .form-field[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:disabled {\n background: #f8f9fa;\n color: #bdbdbd;\n cursor: not-allowed;\n}\n\n.form-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n.form-row[_ngcontent-%COMP%] .form-field[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.checkbox-field[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n.checkbox-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #212121;\n cursor: pointer;\n margin: 0;\n}\n\n.status-bar[_ngcontent-%COMP%] {\n display: flex;\n gap: 24px;\n padding: 16px;\n background: #fafafa;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n margin-bottom: 16px;\n}\n.status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n}\n.status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] .status-label[_ngcontent-%COMP%] {\n color: #666666;\n font-weight: 500;\n}\n.status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] .status-value[_ngcontent-%COMP%] {\n color: #212121;\n font-weight: 600;\n}\n.status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] .status-value.text-success[_ngcontent-%COMP%] {\n color: #4caf50;\n}\n.status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] .status-value.text-warning[_ngcontent-%COMP%] {\n color: #ffc107;\n}\n.status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] .status-value.text-danger[_ngcontent-%COMP%] {\n color: #f44336;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n gap: 16px;\n padding: 48px;\n text-align: center;\n color: #666666;\n}\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n color: #9e9e9e;\n margin-bottom: 8px;\n}\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #212121;\n}\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n line-height: 1.6;\n}\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n gap: 16px;\n padding: 48px;\n}\n.loading-container[_ngcontent-%COMP%] .loading-spinner[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border: 3px solid #e0e0e0;\n border-top-color: #2196f3;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 1s linear infinite;\n}\n.loading-container[_ngcontent-%COMP%] .loading-text[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666666;\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n to {\n transform: rotate(360deg);\n }\n}\n.text-success[_ngcontent-%COMP%] {\n color: #4caf50 !important;\n}\n\n.text-warning[_ngcontent-%COMP%] {\n color: #ffc107 !important;\n}\n\n.text-danger[_ngcontent-%COMP%] {\n color: #f44336 !important;\n}\n\n.text-info[_ngcontent-%COMP%] {\n color: #00bcd4 !important;\n}\n\n.text-muted[_ngcontent-%COMP%] {\n color: #9e9e9e !important;\n}\n\n.text-primary[_ngcontent-%COMP%] {\n color: #212121 !important;\n}\n\n.text-secondary[_ngcontent-%COMP%] {\n color: #666666 !important;\n}\n\n.mb-0[_ngcontent-%COMP%] {\n margin-bottom: 0 !important;\n}\n\n.mb-1[_ngcontent-%COMP%] {\n margin-bottom: 4px !important;\n}\n\n.mb-2[_ngcontent-%COMP%] {\n margin-bottom: 8px !important;\n}\n\n.mb-3[_ngcontent-%COMP%] {\n margin-bottom: 16px !important;\n}\n\n.mb-4[_ngcontent-%COMP%] {\n margin-bottom: 24px !important;\n}\n\n.mb-5[_ngcontent-%COMP%] {\n margin-bottom: 32px !important;\n}\n\n.mt-0[_ngcontent-%COMP%] {\n margin-top: 0 !important;\n}\n\n.mt-1[_ngcontent-%COMP%] {\n margin-top: 4px !important;\n}\n\n.mt-2[_ngcontent-%COMP%] {\n margin-top: 8px !important;\n}\n\n.mt-3[_ngcontent-%COMP%] {\n margin-top: 16px !important;\n}\n\n.mt-4[_ngcontent-%COMP%] {\n margin-top: 24px !important;\n}\n\n.mt-5[_ngcontent-%COMP%] {\n margin-top: 32px !important;\n}\n\n.d-flex[_ngcontent-%COMP%] {\n display: flex !important;\n}\n\n.d-block[_ngcontent-%COMP%] {\n display: block !important;\n}\n\n.d-inline-block[_ngcontent-%COMP%] {\n display: inline-block !important;\n}\n\n.d-none[_ngcontent-%COMP%] {\n display: none !important;\n}\n\n.flex-1[_ngcontent-%COMP%] {\n flex: 1 !important;\n}\n\n.flex-column[_ngcontent-%COMP%] {\n flex-direction: column !important;\n}\n\n.flex-row[_ngcontent-%COMP%] {\n flex-direction: row !important;\n}\n\n.align-center[_ngcontent-%COMP%] {\n align-items: center !important;\n}\n\n.justify-center[_ngcontent-%COMP%] {\n justify-content: center !important;\n}\n\n.justify-between[_ngcontent-%COMP%] {\n justify-content: space-between !important;\n}\n\n.stats-grid[_ngcontent-%COMP%] {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n width: 100%;\n}\n@media (max-width: 768px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card[_ngcontent-%COMP%] {\n margin-right: 10px;\n}\n\n.role-card[_ngcontent-%COMP%] {\n margin-bottom: 5px;\n}\n\n@media (max-width: 768px) {\n .settings-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n .dashboard-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 16px;\n }\n .dashboard-header[_ngcontent-%COMP%] .header-controls[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: flex-start;\n }\n .form-row[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n}\n[_nghost-%COMP%] {\n display: block;\n width: 100%;\n}\n\n.settings-card[_ngcontent-%COMP%] {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.settings-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n.settings-card.settings-card-floating[_ngcontent-%COMP%] {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n}\n.settings-card.settings-card-floating[_ngcontent-%COMP%]:hover {\n box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-2px);\n}\n.settings-card.settings-card-sm[_ngcontent-%COMP%] {\n padding: 16px;\n}\n.settings-card.settings-card-lg[_ngcontent-%COMP%] {\n padding: 24px;\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n padding: 24px 24px 16px 24px;\n margin: 0;\n}\n.card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .card-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-weight: 500;\n color: #212121;\n font-size: 16px;\n}\n.card-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.card-header[_ngcontent-%COMP%] .header-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n.card-header[_ngcontent-%COMP%] .header-content[_ngcontent-%COMP%] .card-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #212121;\n line-height: 1.2;\n}\n.card-header[_ngcontent-%COMP%] .header-content[_ngcontent-%COMP%] .card-subtitle[_ngcontent-%COMP%] {\n margin: 4px 0 0 0;\n font-size: 12px;\n color: #666666;\n line-height: 1.4;\n}\n.card-header[_ngcontent-%COMP%] .header-actions[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: flex;\n gap: 8px;\n align-items: flex-start;\n}\n\n.card-content[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n padding: 0 24px 24px 24px;\n}\n.card-content.no-padding[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.card-footer[_ngcontent-%COMP%] {\n flex-shrink: 0;\n padding: 16px 24px 24px 24px;\n border-top: 1px solid #e0e0e0;\n background: #f8f9fa;\n border-radius: 0 0 8px 8px;\n}\n\n.settings-card-sm[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] {\n padding: 16px 16px 8px 16px;\n}\n.settings-card-sm[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-title[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n.settings-card-sm[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-subtitle[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n.settings-card-sm[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%] {\n padding: 0 16px 16px 16px;\n}\n.settings-card-sm[_ngcontent-%COMP%] .card-content.no-padding[_ngcontent-%COMP%] {\n padding: 0;\n}\n.settings-card-sm[_ngcontent-%COMP%] .card-footer[_ngcontent-%COMP%] {\n padding: 8px 16px 16px 16px;\n}\n\n.settings-card-lg[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] {\n padding: 32px 32px 24px 32px;\n}\n.settings-card-lg[_ngcontent-%COMP%] .card-header[_ngcontent-%COMP%] .card-title[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n.settings-card-lg[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%] {\n padding: 0 32px 32px 32px;\n}\n.settings-card-lg[_ngcontent-%COMP%] .card-content.no-padding[_ngcontent-%COMP%] {\n padding: 0;\n}\n.settings-card-lg[_ngcontent-%COMP%] .card-footer[_ngcontent-%COMP%] {\n padding: 24px 32px 32px 32px;\n}"] });
113
- }
114
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SettingsCardComponent, [{
115
- type: Component,
116
- args: [{ selector: 'mj-settings-card', standalone: true, imports: [CommonModule], template: `
117
- <div class="mj-card"
118
- [class.mj-card-floating]="floating"
119
- [class.mj-card-sm]="size === 'sm'"
120
- [class.mj-card-lg]="size === 'lg'">
121
- @if (title || headerTemplate) {
122
- <div class="mj-card-header">
123
- @if (headerTemplate) {
124
- <ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
125
- } @else {
126
- <div class="header-content">
127
- <h3 class="card-title">{{ title }}</h3>
128
- @if (subtitle) {
129
- <p class="card-subtitle">{{ subtitle }}</p>
130
- }
131
- </div>
132
- @if (actionTemplate) {
133
- <div class="mj-card-actions">
134
- <ng-container *ngTemplateOutlet="actionTemplate"></ng-container>
135
- </div>
136
- }
137
- }
138
- </div>
139
- }
140
-
141
- <div class="mj-card-body" [class.no-padding]="noPadding">
142
- <ng-content></ng-content>
143
- </div>
144
-
145
- @if (footerTemplate) {
146
- <div class="mj-card-footer">
147
- <ng-container *ngTemplateOutlet="footerTemplate"></ng-container>
148
- </div>
149
- }
150
- </div>
151
- `, styles: ["@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n:host {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n font-size: 14px;\n line-height: 1.4;\n color: #212121;\n}\n:host * {\n box-sizing: border-box;\n}\n\n.settings-card {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n padding: 20px;\n}\n.settings-card:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n\n.settings-card-floating {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n padding: 20px;\n}\n.settings-card-floating:hover {\n box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-2px);\n}\n\n.settings-card-sm {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n padding: 16px;\n}\n.settings-card-sm:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n\n.settings-card-lg {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n padding: 24px;\n}\n.settings-card-lg:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n\n.dashboard-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding: 24px 0 16px 0;\n}\n.dashboard-header .header-info {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n.dashboard-header .header-info h1, .dashboard-header .header-info h2, .dashboard-header .header-info h3 {\n margin: 0;\n font-weight: 600;\n color: #212121;\n font-size: 24px;\n line-height: 1.2;\n}\n.dashboard-header .header-info h2 {\n font-size: 18px;\n}\n.dashboard-header .header-info h3 {\n font-size: 16px;\n}\n.dashboard-header .header-controls {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid #e0e0e0;\n}\n.section-header h3, .section-header h4 {\n margin: 0;\n font-weight: 500;\n color: #212121;\n font-size: 16px;\n}\n.section-header h4 {\n font-size: 14px;\n}\n\n.control-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #ffffff;\n color: #212121;\n border-color: #bdbdbd;\n}\n.control-btn:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn i {\n font-size: 14px;\n}\n.control-btn:hover:not(:disabled) {\n background: #f8f9fa;\n border-color: #2196f3;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n.control-btn.control-btn-primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #2196f3;\n color: #ffffff;\n border-color: #2196f3;\n}\n.control-btn.control-btn-primary:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn.control-btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn.control-btn-primary i {\n font-size: 14px;\n}\n.control-btn.control-btn-primary:hover:not(:disabled) {\n background: #1976d2;\n border-color: #1976d2;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.2);\n transform: translateY(-1px);\n}\n.control-btn.control-btn-primary:active {\n transform: translateY(0);\n}\n.control-btn.control-btn-danger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #f44336;\n color: #ffffff;\n border-color: #f44336;\n}\n.control-btn.control-btn-danger:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn.control-btn-danger:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn.control-btn-danger i {\n font-size: 14px;\n}\n.control-btn.control-btn-danger:hover:not(:disabled) {\n background: #ea1c0d;\n border-color: #ea1c0d;\n box-shadow: 0 2px 8px rgba(244, 67, 54, 0.3);\n transform: translateY(-1px);\n}\n.control-btn.control-btn-ghost {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: transparent;\n color: #666666;\n border-color: transparent;\n}\n.control-btn.control-btn-ghost:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.control-btn.control-btn-ghost:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.control-btn.control-btn-ghost i {\n font-size: 14px;\n}\n.control-btn.control-btn-ghost:hover:not(:disabled) {\n background: #f8f9fa;\n color: #2196f3;\n}\n.control-btn.control-btn-sm {\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n}\n.control-btn.control-btn-sm i {\n font-size: 12px;\n}\n.control-btn.control-btn-lg {\n height: 44px;\n padding: 0 24px;\n font-size: 14px;\n}\n.control-btn.control-btn-lg i {\n font-size: 16px;\n}\n\n.action-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: transparent;\n color: #666666;\n border-color: transparent;\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n width: 28px;\n padding: 0;\n}\n.action-btn:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.action-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.action-btn i {\n font-size: 14px;\n}\n.action-btn:hover:not(:disabled) {\n background: #f8f9fa;\n color: #2196f3;\n}\n.action-btn i {\n font-size: 12px;\n}\n.action-btn.action-btn-primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #2196f3;\n color: #ffffff;\n border-color: #2196f3;\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n width: 28px;\n padding: 0;\n}\n.action-btn.action-btn-primary:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.action-btn.action-btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.action-btn.action-btn-primary i {\n font-size: 14px;\n}\n.action-btn.action-btn-primary:hover:not(:disabled) {\n background: #1976d2;\n border-color: #1976d2;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.2);\n transform: translateY(-1px);\n}\n.action-btn.action-btn-primary:active {\n transform: translateY(0);\n}\n.action-btn.action-btn-primary i {\n font-size: 12px;\n}\n.action-btn.action-btn-danger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 0 16px;\n height: 36px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid transparent;\n outline: none;\n white-space: nowrap;\n background: #f44336;\n color: #ffffff;\n border-color: #f44336;\n height: 28px;\n padding: 0 8px;\n font-size: 11px;\n width: 28px;\n padding: 0;\n}\n.action-btn.action-btn-danger:focus {\n outline: 2px solid rgba(33, 150, 243, 0.2);\n outline-offset: 2px;\n}\n.action-btn.action-btn-danger:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n.action-btn.action-btn-danger i {\n font-size: 14px;\n}\n.action-btn.action-btn-danger:hover:not(:disabled) {\n background: #ea1c0d;\n border-color: #ea1c0d;\n box-shadow: 0 2px 8px rgba(244, 67, 54, 0.3);\n transform: translateY(-1px);\n}\n.action-btn.action-btn-danger i {\n font-size: 12px;\n}\n\n.info-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(33, 150, 243, 0.1);\n color: #1976d2;\n border: 1px solid rgba(33, 150, 243, 0.2);\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(158, 158, 158, 0.1);\n color: #666666;\n border: 1px solid rgba(158, 158, 158, 0.2);\n}\n.status-badge.status-active {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(76, 175, 80, 0.1);\n color: #3d8b40;\n border: 1px solid rgba(76, 175, 80, 0.2);\n}\n.status-badge.status-migration {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(33, 150, 243, 0.1);\n color: #1976d2;\n border: 1px solid rgba(33, 150, 243, 0.2);\n}\n.status-badge.status-warning {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(255, 193, 7, 0.1);\n color: #6d5200;\n border: 1px solid rgba(255, 193, 7, 0.2);\n}\n.status-badge.status-error {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n height: 20px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n background: rgba(244, 67, 54, 0.1);\n color: #ea1c0d;\n border: 1px solid rgba(244, 67, 54, 0.2);\n}\n\n.settings-nav {\n width: 220px;\n min-width: 220px;\n max-width: 220px;\n background: #ffffff;\n border-right: 1px solid #e0e0e0;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow-y: auto;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n.settings-nav .nav-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n margin: 0 8px 4px 8px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 400;\n color: #666666;\n text-decoration: none;\n cursor: pointer;\n transition: all 0.15s ease;\n position: relative;\n}\n.settings-nav .nav-item::before {\n content: \"\";\n position: absolute;\n left: 0;\n top: 50%;\n transform: translateY(-50%);\n width: 3px;\n height: 0;\n background: #2196f3;\n border-radius: 0 2px 2px 0;\n transition: height all 0.15s ease;\n}\n.settings-nav .nav-item:hover {\n background: #f8f9fa;\n color: #2196f3;\n transform: translateX(2px);\n}\n.settings-nav .nav-item.active {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n font-weight: 500;\n}\n.settings-nav .nav-item.active::before {\n height: 24px;\n}\n.settings-nav .nav-item i {\n font-size: 14px;\n width: 18px;\n text-align: center;\n}\n\n.form-field {\n margin-bottom: 16px;\n}\n.form-field .field-label {\n display: block;\n margin-bottom: 4px;\n font-size: 12px;\n font-weight: 500;\n color: #212121;\n}\n.form-field .field-hint {\n margin-top: 4px;\n font-size: 11px;\n color: #9e9e9e;\n}\n.form-field .field-error {\n margin-top: 4px;\n font-size: 11px;\n color: #f44336;\n}\n.form-field input, .form-field textarea, .form-field select {\n width: 100%;\n height: 36px;\n padding: 0 8px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 12px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n background: #ffffff;\n color: #212121;\n transition: all 0.15s ease;\n outline: none;\n}\n.form-field input::placeholder, .form-field textarea::placeholder, .form-field select::placeholder {\n color: #9e9e9e;\n}\n.form-field input:focus, .form-field textarea:focus, .form-field select:focus {\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.2);\n}\n.form-field input:disabled, .form-field textarea:disabled, .form-field select:disabled {\n background: #f8f9fa;\n color: #bdbdbd;\n cursor: not-allowed;\n}\n\n.form-row {\n display: flex;\n gap: 16px;\n}\n.form-row .form-field {\n flex: 1;\n}\n\n.checkbox-field {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n.checkbox-field label {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #212121;\n cursor: pointer;\n margin: 0;\n}\n\n.status-bar {\n display: flex;\n gap: 24px;\n padding: 16px;\n background: #fafafa;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n margin-bottom: 16px;\n}\n.status-bar .status-item {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n}\n.status-bar .status-item .status-label {\n color: #666666;\n font-weight: 500;\n}\n.status-bar .status-item .status-value {\n color: #212121;\n font-weight: 600;\n}\n.status-bar .status-item .status-value.text-success {\n color: #4caf50;\n}\n.status-bar .status-item .status-value.text-warning {\n color: #ffc107;\n}\n.status-bar .status-item .status-value.text-danger {\n color: #f44336;\n}\n\n.empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n gap: 16px;\n padding: 48px;\n text-align: center;\n color: #666666;\n}\n.empty-state i {\n font-size: 48px;\n color: #9e9e9e;\n margin-bottom: 8px;\n}\n.empty-state h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #212121;\n}\n.empty-state p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n line-height: 1.6;\n}\n\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n gap: 16px;\n padding: 48px;\n}\n.loading-container .loading-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid #e0e0e0;\n border-top-color: #2196f3;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n.loading-container .loading-text {\n font-size: 12px;\n color: #666666;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n.text-success {\n color: #4caf50 !important;\n}\n\n.text-warning {\n color: #ffc107 !important;\n}\n\n.text-danger {\n color: #f44336 !important;\n}\n\n.text-info {\n color: #00bcd4 !important;\n}\n\n.text-muted {\n color: #9e9e9e !important;\n}\n\n.text-primary {\n color: #212121 !important;\n}\n\n.text-secondary {\n color: #666666 !important;\n}\n\n.mb-0 {\n margin-bottom: 0 !important;\n}\n\n.mb-1 {\n margin-bottom: 4px !important;\n}\n\n.mb-2 {\n margin-bottom: 8px !important;\n}\n\n.mb-3 {\n margin-bottom: 16px !important;\n}\n\n.mb-4 {\n margin-bottom: 24px !important;\n}\n\n.mb-5 {\n margin-bottom: 32px !important;\n}\n\n.mt-0 {\n margin-top: 0 !important;\n}\n\n.mt-1 {\n margin-top: 4px !important;\n}\n\n.mt-2 {\n margin-top: 8px !important;\n}\n\n.mt-3 {\n margin-top: 16px !important;\n}\n\n.mt-4 {\n margin-top: 24px !important;\n}\n\n.mt-5 {\n margin-top: 32px !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-none {\n display: none !important;\n}\n\n.flex-1 {\n flex: 1 !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.align-center {\n align-items: center !important;\n}\n\n.justify-center {\n justify-content: center !important;\n}\n\n.justify-between {\n justify-content: space-between !important;\n}\n\n.stats-grid {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n width: 100%;\n}\n@media (max-width: 768px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card {\n margin-right: 10px;\n}\n\n.role-card {\n margin-bottom: 5px;\n}\n\n@media (max-width: 768px) {\n .settings-card {\n padding: 16px;\n }\n .dashboard-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 16px;\n }\n .dashboard-header .header-controls {\n width: 100%;\n justify-content: flex-start;\n }\n .form-row {\n flex-direction: column;\n }\n}\n:host {\n display: block;\n width: 100%;\n}\n\n.settings-card {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.settings-card:hover {\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-1px);\n}\n.settings-card.settings-card-floating {\n background: #ffffff;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n}\n.settings-card.settings-card-floating:hover {\n box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);\n transform: translateY(-2px);\n}\n.settings-card.settings-card-sm {\n padding: 16px;\n}\n.settings-card.settings-card-lg {\n padding: 24px;\n}\n\n.card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n padding: 24px 24px 16px 24px;\n margin: 0;\n}\n.card-header h3, .card-header h4 {\n margin: 0;\n font-weight: 500;\n color: #212121;\n font-size: 16px;\n}\n.card-header h4 {\n font-size: 14px;\n}\n.card-header .header-content {\n flex: 1;\n}\n.card-header .header-content .card-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #212121;\n line-height: 1.2;\n}\n.card-header .header-content .card-subtitle {\n margin: 4px 0 0 0;\n font-size: 12px;\n color: #666666;\n line-height: 1.4;\n}\n.card-header .header-actions {\n flex-shrink: 0;\n display: flex;\n gap: 8px;\n align-items: flex-start;\n}\n\n.card-content {\n flex: 1;\n min-height: 0;\n padding: 0 24px 24px 24px;\n}\n.card-content.no-padding {\n padding: 0;\n}\n\n.card-footer {\n flex-shrink: 0;\n padding: 16px 24px 24px 24px;\n border-top: 1px solid #e0e0e0;\n background: #f8f9fa;\n border-radius: 0 0 8px 8px;\n}\n\n.settings-card-sm .card-header {\n padding: 16px 16px 8px 16px;\n}\n.settings-card-sm .card-header .card-title {\n font-size: 14px;\n}\n.settings-card-sm .card-header .card-subtitle {\n font-size: 11px;\n}\n.settings-card-sm .card-content {\n padding: 0 16px 16px 16px;\n}\n.settings-card-sm .card-content.no-padding {\n padding: 0;\n}\n.settings-card-sm .card-footer {\n padding: 8px 16px 16px 16px;\n}\n\n.settings-card-lg .card-header {\n padding: 32px 32px 24px 32px;\n}\n.settings-card-lg .card-header .card-title {\n font-size: 18px;\n}\n.settings-card-lg .card-content {\n padding: 0 32px 32px 32px;\n}\n.settings-card-lg .card-content.no-padding {\n padding: 0;\n}\n.settings-card-lg .card-footer {\n padding: 24px 32px 32px 32px;\n}\n"] }]
152
- }], null, { title: [{
153
- type: Input
154
- }], subtitle: [{
155
- type: Input
156
- }], floating: [{
157
- type: Input
158
- }], size: [{
159
- type: Input
160
- }], noPadding: [{
161
- type: Input
162
- }], headerTemplate: [{
163
- type: Input
164
- }], actionTemplate: [{
165
- type: Input
166
- }], footerTemplate: [{
167
- type: Input
168
- }] }); })();
169
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SettingsCardComponent, { className: "SettingsCardComponent" }); })();
170
- //# sourceMappingURL=settings-card.component.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings-card.component.js","sourceRoot":"","sources":["../../../../../src/lib/shared/components/settings-card/settings-card.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAe,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;;;;;IAkBnC,wBAAgE;;;IAAhE,oHAAiD;;;IAAlC,wDAAgC;;;IAK3C,4BAAyB;IAAA,YAAc;IAAA,iBAAI;;;IAAlB,cAAc;IAAd,qCAAc;;;IAKvC,wBAAgE;;;IADlE,8BAA6B;IAC3B,kIAAiD;IACnD,iBAAM;;;IADW,cAAgC;IAAhC,wDAAgC;;;IAPjD,AADF,8BAA4B,YACH;IAAA,YAAW;IAAA,iBAAK;IACvC,wGAAgB;IAGlB,iBAAM;IACN,0GAAsB;;;IALG,eAAW;IAAX,kCAAW;IAClC,cAEC;IAFD,0CAEC;IAEH,cAIC;IAJD,gDAIC;;;IAdL,8BAA4B;IAGxB,AAFF,kGAAsB,qEAEb;IAaX,iBAAM;;;IAfJ,cAcC;IAdD,+CAcC;;;IAUD,wBAAgE;;;IADlE,8BAA4B;IAC1B,sGAAiD;IACnD,iBAAM;;;IADW,cAAgC;IAAhC,wDAAgC;;AAvCzD;;;GAGG;AA2CH,MAAM,OAAO,qBAAqB;IAChC,yCAAyC;IAChC,KAAK,CAAU;IAExB,8CAA8C;IACrC,QAAQ,CAAU;IAE3B,4DAA4D;IACnD,QAAQ,GAAG,KAAK,CAAC;IAE1B,wBAAwB;IACf,IAAI,GAAuB,IAAI,CAAC;IAEzC,kDAAkD;IACzC,SAAS,GAAG,KAAK,CAAC;IAE3B,yCAAyC;IAChC,cAAc,CAAoB;IAE3C,yCAAyC;IAChC,cAAc,CAAoB;IAE3C,kCAAkC;IACzB,cAAc,CAAoB;+EAvBhC,qBAAqB;6DAArB,qBAAqB;;YArC9B,8BAGwC;YACtC,8EAA+B;YAoB/B,8BAAyD;YACvD,kBAAyB;YAC3B,iBAAM;YAEN,8EAAsB;YAKxB,iBAAM;;YA9BD,AADA,AADA,gDAAmC,iCACD,iCACA;YACrC,cAkBC;YAlBD,0DAkBC;YAEyB,cAA8B;YAA9B,2CAA8B;YAIxD,eAIC;YAJD,6CAIC;4BAlCK,YAAY;;iFAuCX,qBAAqB;cA1CjC,SAAS;2BACE,kBAAkB,cAChB,IAAI,WACP,CAAC,YAAY,CAAC,YACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCT;gBAKQ,KAAK;kBAAb,KAAK;YAGG,QAAQ;kBAAhB,KAAK;YAGG,QAAQ;kBAAhB,KAAK;YAGG,IAAI;kBAAZ,KAAK;YAGG,SAAS;kBAAjB,KAAK;YAGG,cAAc;kBAAtB,KAAK;YAGG,cAAc;kBAAtB,KAAK;YAGG,cAAc;kBAAtB,KAAK;;kFAvBK,qBAAqB"}