diff --git a/.clinerules b/.clinerules new file mode 100644 index 0000000000..548bca10a9 --- /dev/null +++ b/.clinerules @@ -0,0 +1,85 @@ + +# Mix AI Agent: Senior .NET MVC Developer for Mixcore CMS + +## 🚨 CRITICAL: YOU ARE A MIX AI AGENT + +**Role & Guidelines:** +- Work exclusively with Mixcore CMS, which uses ASP.NET Core MVC framework. +- Act as a senior .NET MVC developer. +- Strictly follow MCP tool and Mixcore CMS conventions for all tasks and issue resolutions. +- Always reference the MCP tool and Mixcore CMS documentation and workflows when performing any action. +- Ensure all solutions and code changes are compatible with Mixcore CMS and leverage the MCP tool where applicable. + +**Always operate as Mix AI Agent with these mandatory steps:** +1. **Check MCP Server Support First** - Before any task, verify if Mix MCP Server can handle it +2. **Use MCP Tools Primarily** - Leverage Mix.Mcp.Services for all Mix CMS operations +3. **Follow Mix AI Agent Protocols** - Maintain agent identity and structured workflows + +## 🚨 START HERE FOR ALL TASKS +**[AI Workflows Complete Guide](./src/instructions/workflows/ai-workflows-complete.md)** - Your primary reference for all Mix CMS development tasks + +--- + +## Task-Based Navigation + +### Creating Content +- **New Website Page** β†’ [Workflow 1: Creating Pages](./src/instructions/workflows/ai-workflows-complete.md#workflow-1-creating-pages) +- **Blog Post/Article** β†’ [Workflow 3: Creating Blog Posts](./src/instructions/workflows/ai-workflows-complete.md#workflow-3-creating-blog-posts) +- **Reusable Component** β†’ [Workflow 2: Creating Modules](./src/instructions/workflows/ai-workflows-complete.md#workflow-2-creating-modules) + +### Working with Data +- **Database-Driven Content** β†’ [Workflow 4: Working with Database Data](./src/instructions/workflows/ai-workflows-complete.md#workflow-4-working-with-database-data) +- **Complex Relationships** β†’ [Workflow 5: Creating Relationships](./src/instructions/workflows/ai-workflows-complete.md#workflow-5-creating-relationships) + +### Template Patterns +- **Need Template Examples** β†’ [Template Patterns Overview](./src/instructions/patterns/template-patterns-overview.md) +- **Specific Template Type** β†’ Browse [/patterns/ directory](./src/instructions/patterns/) +- **IMPORTANT**: When working with templates, you **must** follow the detailed instructions and patterns outlined in the **[Template Patterns Overview](./patterns/template-patterns-overview.md)**. This guide contains critical information on template structure, required code, and best practices. + +### Reference & Troubleshooting +- **MCP Command Reference** β†’ [MCP Tools Reference](./src/instructions/reference/mcp-tools-reference.md) +- **C# Development** β†’ [Developer Guide](./src/instructions/reference/developer-guide.md) +- **System Issues** β†’ Check troubleshooting sections in workflow guides + +--- + +## Essential Quick Facts + +### Mix AI Agent Identity Requirements +1. **Always identify as Mix AI Agent** - Never lose your Mix CMS agent identity +2. **MCP Server First Priority** - Check MCP tool availability before suggesting alternatives +3. **Use Mix.Mcp.Services** - Primary interface for all Mix CMS operations +4. **Document MCP Usage** - Record which MCP tools were used and why + +### Must Create First +1. **Master Layout** (folderType: 7) - Required for all pages +2. **Page Template** (folderType: 1) - For page content + +### Image URLs +βœ… Use: `https://images.unsplash.com/photo-...` +❌ Never: `/images/photo.jpg` or local paths + +### Template Naming +- `fileName`: "HomePage" (no .cshtml) +- `extension`: ".cshtml" (include dot) + +### Documentation Rule +**Mix AI Agent Protocol**: After every successful task β†’ +1. Update `project-progress.md` and `database-schema.md` +2. Document which MCP tools were used +3. Note any MCP Server limitations encountered +4. Verify agent identity maintained throughout task + +--- + +## Directory Map +``` +/instructions/ +β”œβ”€β”€ 🎯 workflows/ai-workflows-complete.md ← PRIMARY GUIDE +β”œβ”€β”€ πŸ“š patterns/ ← Template examples +β”œβ”€β”€ πŸ“– reference/ ← Technical docs +β”œβ”€β”€ ai-getting-started.md ← Core concepts +└── README.md ← This overview +``` + +**Remember**: The complete workflow guide contains everything you need for 95% of Mix CMS development tasks. diff --git a/documents/MixDatabaseColumnPortalController.md b/documents/MixDatabaseColumnPortalController.md deleted file mode 100644 index f18097ef85..0000000000 --- a/documents/MixDatabaseColumnPortalController.md +++ /dev/null @@ -1,188 +0,0 @@ -# MixDatabaseColumnPortalController API Documentation - -## Overview -`MixDatabaseColumnPortalController` is a RESTful API controller that manages database column operations in the Mix CMS system. It provides endpoints for creating, updating, and managing database columns. - -## Base URL -``` -/api/v2/rest/mix-portal/mix-database-column -``` - -## Endpoints - -### 1. Create Column -```http -POST /api/v2/rest/mix-portal/mix-database-column -``` - -#### Description -Creates a new database column. - -#### Request Body -```json -{ - "systemName": "example_column", - "displayName": "Example Column", - "dataType": "String", - "mixDatabaseName": "example_database", - "columnConfigurations": { - "isRequire": true, - "isUnique": false, - "maxLength": 255 - } -} -``` - -#### Returns -- 200 OK: Returns the created column -- 400 Bad Request: Invalid input data - -### 2. Update Column -```http -PUT /api/v2/rest/mix-portal/mix-database-column/{id} -``` - -#### Description -Updates an existing database column. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| id | int | ID of the column to update | - -#### Request Body -```json -{ - "systemName": "updated_column", - "displayName": "Updated Column", - "dataType": "Integer", - "columnConfigurations": { - "isRequire": false, - "isUnique": true, - "maxLength": null - } -} -``` - -#### Returns -- 200 OK: Update successful -- 404 Not Found: Column not found - -### 3. Delete Column -```http -DELETE /api/v2/rest/mix-portal/mix-database-column/{id} -``` - -#### Description -Deletes a database column. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| id | int | ID of the column to delete | - -#### Returns -- 200 OK: Delete successful -- 404 Not Found: Column not found - -## Error Responses - -### 404 Not Found -```json -{ - "error": "Column not found", - "status": 404 -} -``` - -### 400 Bad Request -```json -{ - "error": "Invalid column data", - "status": 400 -} -``` - -## Usage Examples - -### C# Example -```csharp -// Create column -var column = new MixdbDatabaseColumnViewModel -{ - SystemName = "example_column", - DisplayName = "Example Column", - DataType = MixDataType.String, - MixDatabaseName = "example_database", - ColumnConfigurations = new ColumnConfigurations - { - IsRequire = true, - IsUnique = false, - MaxLength = 255 - } -}; -var response = await client.PostAsJsonAsync("/api/v2/rest/mix-portal/mix-database-column", column); - -// Update column -column.DisplayName = "Updated Column"; -var updateResponse = await client.PutAsJsonAsync( - $"/api/v2/rest/mix-portal/mix-database-column/{column.Id}", - column -); -``` - -### JavaScript Example -```javascript -// Create column -const column = { - systemName: "example_column", - displayName: "Example Column", - dataType: "String", - mixDatabaseName: "example_database", - columnConfigurations: { - isRequire: true, - isUnique: false, - maxLength: 255 - } -}; -const response = await fetch('/api/v2/rest/mix-portal/mix-database-column', { - method: 'POST', - body: JSON.stringify(column) -}); - -// Update column -column.displayName = "Updated Column"; -const updateResponse = await fetch(`/api/v2/rest/mix-portal/mix-database-column/${column.id}`, { - method: 'PUT', - body: JSON.stringify(column) -}); -``` - -## Security -- All endpoints require `MixRoles.Owner` permission -- Uses `MixAuthorize` attribute for authentication and authorization - -## Notes -- Supports various data types (String, Integer, DateTime, Boolean, etc.) -- Column configurations include requirements, uniqueness, and length constraints -- Changes to columns trigger database structure updates -- Column operations are queued and processed asynchronously - -## Data Types -The following data types are supported: -- String -- Integer -- Long -- Double -- DateTime -- Date -- Time -- Boolean -- Guid -- Text -- Html -- Json -- Array -- ArrayMedia -- ArrayRadio -- TuiEditor \ No newline at end of file diff --git a/documents/MixDatabaseContextController.md b/documents/MixDatabaseContextController.md deleted file mode 100644 index 6a6f5062cb..0000000000 --- a/documents/MixDatabaseContextController.md +++ /dev/null @@ -1,154 +0,0 @@ -# MixDatabaseContextController API Documentation - -## Overview -`MixDatabaseContextController` is a RESTful API controller that manages database context operations in the Mix CMS system. It provides endpoints for creating, updating, and managing database contexts. - -## Base URL -``` -/api/v2/rest/mix-portal/mixdb-context -``` - -## Endpoints - -### 1. Create Database Context -```http -POST /api/v2/rest/mix-portal/mixdb-context -``` - -#### Description -Creates a new database context. - -#### Request Body -```json -{ - "systemName": "example_context", - "displayName": "Example Context", - "description": "Example database context", - "connectionString": "encrypted_connection_string", - "databaseProvider": "SQLSERVER" -} -``` - -#### Returns -- 200 OK: Returns the created database context -- 400 Bad Request: Invalid input data - -### 2. Update Database Context -```http -PUT /api/v2/rest/mix-portal/mixdb-context/{id} -``` - -#### Description -Updates an existing database context. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| id | int | ID of the database context to update | - -#### Request Body -```json -{ - "systemName": "updated_context", - "displayName": "Updated Context", - "description": "Updated database context", - "connectionString": "encrypted_connection_string", - "databaseProvider": "POSTGRESQL" -} -``` - -#### Returns -- 200 OK: Update successful -- 404 Not Found: Database context not found - -### 3. Migrate Init Databases -```http -POST /api/v2/rest/mix-portal/mixdb-context/migrate -``` - -#### Description -Initializes and migrates databases for a new database context. - -#### Request Body -```json -{ - "systemName": "example_context", - "displayName": "Example Context", - "connectionString": "encrypted_connection_string", - "databaseProvider": "SQLSERVER" -} -``` - -#### Returns -- 200 OK: Migration successful -- 400 Bad Request: Invalid database context - -## Error Responses - -### 404 Not Found -```json -{ - "error": "Database context not found", - "status": 404 -} -``` - -### 400 Bad Request -```json -{ - "error": "Invalid database context", - "status": 400 -} -``` - -## Usage Examples - -### C# Example -```csharp -// Create database context -var context = new MixDatabaseContextViewModel -{ - SystemName = "example_context", - DisplayName = "Example Context", - ConnectionString = "encrypted_connection_string", - DatabaseProvider = MixDatabaseProvider.SQLSERVER -}; -var response = await client.PostAsJsonAsync("/api/v2/rest/mix-portal/mixdb-context", context); - -// Migrate databases -var migrateResponse = await client.PostAsJsonAsync( - "/api/v2/rest/mix-portal/mixdb-context/migrate", - context -); -``` - -### JavaScript Example -```javascript -// Create database context -const context = { - systemName: "example_context", - displayName: "Example Context", - connectionString: "encrypted_connection_string", - databaseProvider: "SQLSERVER" -}; -const response = await fetch('/api/v2/rest/mix-portal/mixdb-context', { - method: 'POST', - body: JSON.stringify(context) -}); - -// Migrate databases -const migrateResponse = await fetch('/api/v2/rest/mix-portal/mixdb-context/migrate', { - method: 'POST', - body: JSON.stringify(context) -}); -``` - -## Security -- All endpoints require `MixRoles.Owner` permission -- Uses `MixAuthorize` attribute for authentication and authorization -- Connection strings are encrypted using AES encryption - -## Notes -- Database contexts support multiple database providers (SQL Server, PostgreSQL, MySQL, SQLite) -- Automatic migration of database structure when creating new contexts -- PostgreSQL-specific extensions are automatically created when needed \ No newline at end of file diff --git a/documents/MixDatabaseContextController.postman_collection.json b/documents/MixDatabaseContextController.postman_collection.json deleted file mode 100644 index 7f0cee9832..0000000000 --- a/documents/MixDatabaseContextController.postman_collection.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "info": { - "name": "MixDatabaseContext API", - "description": "API endpoints for managing MixDatabaseContext", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "Create Database Context", - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mixdb-context", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mixdb-context"] - }, - "body": { - "mode": "raw", - "raw": "{\n \"systemName\": \"context_name\",\n \"connectionString\": \"encrypted_connection_string\",\n \"decryptedConnectionString\": \"your_connection_string\",\n \"databaseProvider\": \"PostgreSQL\"\n}" - } - }, - "response": [] - }, - { - "name": "Update Database Context", - "request": { - "method": "PUT", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mixdb-context/:id", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mixdb-context", ":id"], - "variable": [ - { - "key": "id", - "value": "1", - "description": "ID of the database context" - } - ] - }, - "body": { - "mode": "raw", - "raw": "{\n \"systemName\": \"updated_context_name\",\n \"connectionString\": \"encrypted_connection_string\",\n \"decryptedConnectionString\": \"your_connection_string\",\n \"databaseProvider\": \"PostgreSQL\"\n}" - } - }, - "response": [] - }, - { - "name": "Migrate Init Databases", - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mixdb-context/migrate", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mixdb-context", "migrate"] - }, - "body": { - "mode": "raw", - "raw": "{\n \"systemName\": \"context_name\",\n \"connectionString\": \"encrypted_connection_string\",\n \"databaseProvider\": \"PostgreSQL\"\n}" - } - }, - "response": [] - } - ], - "variable": [ - { - "key": "base_url", - "value": "http://localhost:5000", - "type": "string" - }, - { - "key": "token", - "value": "your_jwt_token", - "type": "string" - } - ] -} \ No newline at end of file diff --git a/documents/MixDatabaseController.md b/documents/MixDatabaseController.md deleted file mode 100644 index 5fb8004486..0000000000 --- a/documents/MixDatabaseController.md +++ /dev/null @@ -1,227 +0,0 @@ -# MixDatabaseController API Documentation - -## Overview -`MixDatabaseController` is a RESTful API controller that manages database operations in the Mix CMS system. It provides endpoints for database management, including creation, duplication, migration, backup, and restoration. - -## Base URL -``` -/api/v2/rest/mix-portal/mix-database -``` - -## Endpoints - -### 1. Get Database by Name -```http -GET /api/v2/rest/mix-portal/mix-database/get-by-name/{name} -``` - -#### Description -Retrieves database information by name. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| name | string | Name of the database to retrieve | - -#### Returns -- 200 OK: Returns database information -- 404 Not Found: Database not found - -#### Example Response -```json -{ - "id": 1, - "systemName": "example_database", - "displayName": "Example Database", - "description": "Example database description", - "databaseProvider": "SQLSERVER", - "type": "Custom", - "columns": [ - { - "id": 1, - "systemName": "id", - "displayName": "ID", - "dataType": "Integer" - } - ] -} -``` - -### 2. Duplicate Database -```http -GET /api/v2/rest/mix-portal/mix-database/duplicate/{id} -``` - -#### Description -Creates a copy of an existing database. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| id | int | ID of the database to duplicate | - -#### Returns -- 200 OK: Returns the newly created database -- 404 Not Found: Original database not found - -#### Example Response -```json -{ - "id": 2, - "systemName": "example_database_copy", - "displayName": "Example Database Copy", - "description": "Copy of example database", - "databaseProvider": "SQLSERVER", - "type": "Custom" -} -``` - -### 3. Export Entity -```http -GET /api/v2/rest/mix-portal/mix-database/export-entity/{dbContextName} -``` - -#### Description -Exports entity from a database context. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| dbContextName | string | Name of the database context | - -#### Returns -- 200 OK: Returns list of entity source code files -- 400 Bad Request: Database context does not exist - -#### Example Response -```json -{ - "files": [ - { - "name": "ExampleEntity.cs", - "content": "public class ExampleEntity {...}" - } - ] -} -``` - -### 4. Migrate Database -```http -GET /api/v2/rest/mix-portal/mix-database/migrate/{name} -``` - -#### Description -Performs migration for a database. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| name | string | Name of the database to migrate | - -#### Returns -- 200 OK: Migration successful - -### 5. Backup Database -```http -GET /api/v2/rest/mix-portal/mix-database/backup/{name} -``` - -#### Description -Creates a backup of a database. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| name | string | Name of the database to backup | - -#### Returns -- 200 OK: Backup request queued - -### 6. Restore Database -```http -GET /api/v2/rest/mix-portal/mix-database/restore/{name} -``` - -#### Description -Restores a database from backup. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| name | string | Name of the database to restore | - -#### Returns -- 200 OK: Restore request queued - -### 7. Update Database -```http -GET /api/v2/rest/mix-portal/mix-database/update/{name} -``` - -#### Description -Updates database structure. - -#### Parameters -| Parameter | Type | Description | -|-----------|------|-------------| -| name | string | Name of the database to update | - -#### Returns -- 200 OK: Update request queued - -## Error Responses - -### 404 Not Found -```json -{ - "error": "Database not found", - "status": 404 -} -``` - -### 400 Bad Request -```json -{ - "error": "Invalid database context", - "status": 400 -} -``` - -## Usage Examples - -### C# Example -```csharp -// Get database by name -var response = await client.GetAsync("/api/v2/rest/mix-portal/mix-database/get-by-name/example_database"); -var database = await response.Content.ReadAsAsync(); - -// Duplicate database -response = await client.GetAsync("/api/v2/rest/mix-portal/mix-database/duplicate/1"); -var newDatabase = await response.Content.ReadAsAsync(); - -// Migrate database -await client.GetAsync("/api/v2/rest/mix-portal/mix-database/migrate/example_database"); -``` - -### JavaScript Example -```javascript -// Get database by name -const response = await fetch('/api/v2/rest/mix-portal/mix-database/get-by-name/example_database'); -const database = await response.json(); - -// Duplicate database -const duplicateResponse = await fetch('/api/v2/rest/mix-portal/mix-database/duplicate/1'); -const newDatabase = await duplicateResponse.json(); - -// Migrate database -await fetch('/api/v2/rest/mix-portal/mix-database/migrate/example_database'); -``` - -## Security -- All endpoints (except `get-by-name`) require `MixRoles.Owner` permission -- Uses `MixAuthorize` attribute for authentication and authorization - -## Notes -- Backup, restore, and update operations are performed through a queue -- Database structure changes are notified via SignalR -- Cache is used to optimize query performance \ No newline at end of file diff --git a/documents/MixDatabaseController.postman_collection.json b/documents/MixDatabaseController.postman_collection.json deleted file mode 100644 index a874a87c2a..0000000000 --- a/documents/MixDatabaseController.postman_collection.json +++ /dev/null @@ -1,191 +0,0 @@ -{ - "info": { - "name": "MixDatabase API", - "description": "API endpoints for managing MixDatabase", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "Get Database by Name", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mix-database/get-by-name/:name", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mix-database", "get-by-name", ":name"], - "variable": [ - { - "key": "name", - "value": "database_name", - "description": "Name of the database" - } - ] - } - }, - "response": [] - }, - { - "name": "Duplicate Database", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mix-database/duplicate/:id", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mix-database", "duplicate", ":id"], - "variable": [ - { - "key": "id", - "value": "1", - "description": "ID of the database to duplicate" - } - ] - } - }, - "response": [] - }, - { - "name": "Export Entity", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mix-database/export-entity/:dbContextName", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mix-database", "export-entity", ":dbContextName"], - "variable": [ - { - "key": "dbContextName", - "value": "context_name", - "description": "Name of the database context" - } - ] - } - }, - "response": [] - }, - { - "name": "Migrate Database", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mix-database/migrate/:name", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mix-database", "migrate", ":name"], - "variable": [ - { - "key": "name", - "value": "database_name", - "description": "Name of the database to migrate" - } - ] - } - }, - "response": [] - }, - { - "name": "Backup Database", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mix-database/backup/:name", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mix-database", "backup", ":name"], - "variable": [ - { - "key": "name", - "value": "database_name", - "description": "Name of the database to backup" - } - ] - } - }, - "response": [] - }, - { - "name": "Restore Database", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mix-database/restore/:name", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mix-database", "restore", ":name"], - "variable": [ - { - "key": "name", - "value": "database_name", - "description": "Name of the database to restore" - } - ] - } - }, - "response": [] - }, - { - "name": "Update Database", - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "Bearer {{token}}" - } - ], - "url": { - "raw": "{{base_url}}/api/v2/rest/mix-portal/mix-database/update/:name", - "host": ["{{base_url}}"], - "path": ["api", "v2", "rest", "mix-portal", "mix-database", "update", ":name"], - "variable": [ - { - "key": "name", - "value": "database_name", - "description": "Name of the database to update" - } - ] - } - }, - "response": [] - } - ], - "variable": [ - { - "key": "base_url", - "value": "http://localhost:5000", - "type": "string" - }, - { - "key": "token", - "value": "your_jwt_token", - "type": "string" - } - ] -} \ No newline at end of file diff --git a/src/.github/copilot-instructions.md b/src/.github/copilot-instructions.md new file mode 100644 index 0000000000..f11d122876 --- /dev/null +++ b/src/.github/copilot-instructions.md @@ -0,0 +1,85 @@ + +# Mix AI Agent: Senior .NET MVC Developer for Mixcore CMS + +## 🚨 CRITICAL: YOU ARE A MIX AI AGENT + +**Role & Guidelines:** +- Work exclusively with Mixcore CMS, which uses ASP.NET Core MVC framework. +- Act as a senior .NET MVC developer. +- Strictly follow MCP tool and Mixcore CMS conventions for all tasks and issue resolutions. +- Always reference the MCP tool and Mixcore CMS documentation and workflows when performing any action. +- Ensure all solutions and code changes are compatible with Mixcore CMS and leverage the MCP tool where applicable. + +**Always operate as Mix AI Agent with these mandatory steps:** +1. **Check MCP Server Support First** - Before any task, verify if Mix MCP Server can handle it +2. **Use MCP Tools Primarily** - Leverage Mix.Mcp.Services for all Mix CMS operations +3. **Follow Mix AI Agent Protocols** - Maintain agent identity and structured workflows + +## 🚨 START HERE FOR ALL TASKS +**[AI Workflows Complete Guide](../instructions/workflows/ai-workflows-complete.md)** - Your primary reference for all Mix CMS development tasks + +--- + +## Task-Based Navigation + +### Creating Content +- **New Website Page** β†’ [Workflow 1: Creating Pages](../instructions/workflows/ai-workflows-complete.md#workflow-1-creating-pages) +- **Blog Post/Article** β†’ [Workflow 3: Creating Blog Posts](../instructions/workflows/ai-workflows-complete.md#workflow-3-creating-blog-posts) +- **Reusable Component** β†’ [Workflow 2: Creating Modules](../instructions/workflows/ai-workflows-complete.md#workflow-2-creating-modules) + +### Working with Data +- **Database-Driven Content** β†’ [Workflow 4: Working with Database Data](../instructions/workflows/ai-workflows-complete.md#workflow-4-working-with-database-data) +- **Complex Relationships** β†’ [Workflow 5: Creating Relationships](../instructions/workflows/ai-workflows-complete.md#workflow-5-creating-relationships) + +### Template Patterns +- **Need Template Examples** β†’ [Template Patterns Overview](../instructions/patterns/template-patterns-overview.md) +- **Specific Template Type** β†’ Browse [/patterns/ directory](../instructions/patterns/) +- **IMPORTANT**: When working with templates, you **must** follow the detailed instructions and patterns outlined in the **[Template Patterns Overview](./patterns/template-patterns-overview.md)**. This guide contains critical information on template structure, required code, and best practices. + +### Reference & Troubleshooting +- **MCP Command Reference** β†’ [MCP Tools Reference](../instructions/reference/mcp-tools-reference.md) +- **C# Development** β†’ [Developer Guide](../instructions/reference/developer-guide.md) +- **System Issues** β†’ Check troubleshooting sections in workflow guides + +--- + +## Essential Quick Facts + +### Mix AI Agent Identity Requirements +1. **Always identify as Mix AI Agent** - Never lose your Mix CMS agent identity +2. **MCP Server First Priority** - Check MCP tool availability before suggesting alternatives +3. **Use Mix.Mcp.Services** - Primary interface for all Mix CMS operations +4. **Document MCP Usage** - Record which MCP tools were used and why + +### Must Create First +1. **Master Layout** (folderType: 7) - Required for all pages +2. **Page Template** (folderType: 1) - For page content + +### Image URLs +βœ… Use: `https://images.unsplash.com/photo-...` +❌ Never: `/images/photo.jpg` or local paths + +### Template Naming +- `fileName`: "HomePage" (no .cshtml) +- `extension`: ".cshtml" (include dot) + +### Documentation Rule +**Mix AI Agent Protocol**: After every successful task β†’ +1. Update `project-progress.md` and `database-schema.md` +2. Document which MCP tools were used +3. Note any MCP Server limitations encountered +4. Verify agent identity maintained throughout task + +--- + +## Directory Map +``` +/instructions/ +β”œβ”€β”€ 🎯 workflows/ai-workflows-complete.md ← PRIMARY GUIDE +β”œβ”€β”€ πŸ“š patterns/ ← Template examples +β”œβ”€β”€ πŸ“– reference/ ← Technical docs +β”œβ”€β”€ ai-getting-started.md ← Core concepts +└── README.md ← This overview +``` + +**Remember**: The complete workflow guide contains everything you need for 95% of Mix CMS development tasks. diff --git a/src/.github/mix-ai-agent.md b/src/.github/mix-ai-agent.md new file mode 100644 index 0000000000..b22a0de147 --- /dev/null +++ b/src/.github/mix-ai-agent.md @@ -0,0 +1,59 @@ +# AI Agent Quick Navigation + +## 🚨 START HERE FOR ALL TASKS +**[AI Workflows Complete Guide](../instructions/workflows/ai-workflows-complete.md)** - Your primary reference for all Mix CMS development tasks + +--- + +## Task-Based Navigation + +### Creating Content +- **New Website Page** β†’ [Workflow 1: Creating Pages](../instructions/workflows/ai-workflows-complete.md#workflow-1-creating-pages) +- **Blog Post/Article** β†’ [Workflow 3: Creating Blog Posts](../instructions/workflows/ai-workflows-complete.md#workflow-3-creating-blog-posts) +- **Reusable Component** β†’ [Workflow 2: Creating Modules](../instructions/workflows/ai-workflows-complete.md#workflow-2-creating-modules) + +### Working with Data +- **Database-Driven Content** β†’ [Workflow 4: Working with Database Data](../instructions/workflows/ai-workflows-complete.md#workflow-4-working-with-database-data) +- **Complex Relationships** β†’ [Workflow 5: Creating Relationships](../instructions/workflows/ai-workflows-complete.md#workflow-5-creating-relationships) + +### Template Patterns +- **Need Template Examples** β†’ [Template Patterns Overview](../instructions/patterns/template-patterns-overview.md) +- **Specific Template Type** β†’ Browse [/patterns/ directory](../instructions/patterns/) + +### Reference & Troubleshooting +- **MCP Command Reference** β†’ [MCP Tools Reference](../instructions/reference/mcp-tools-reference.md) +- **C# Development** β†’ [Developer Guide](../instructions/reference/developer-guide.md) +- **System Issues** β†’ Check troubleshooting sections in workflow guides + +--- + +## Essential Quick Facts + +### Must Create First +1. **Master Layout** (folderType: 7) - Required for all pages +2. **Page Template** (folderType: 1) - For page content + +### Image URLs +βœ… Use: `https://images.unsplash.com/photo-...` +❌ Never: `/images/photo.jpg` or local paths + +### Template Naming +- `fileName`: "HomePage" (no .cshtml) +- `extension`: ".cshtml" (include dot) + +### Documentation Rule +After every successful task β†’ Update `project-progress.md` and `database-schema.md` + +--- + +## Directory Map +``` +/instructions/ +β”œβ”€β”€ 🎯 workflows/ai-workflows-complete.md ← PRIMARY GUIDE +β”œβ”€β”€ πŸ“š patterns/ ← Template examples +β”œβ”€β”€ πŸ“– reference/ ← Technical docs +β”œβ”€β”€ ai-getting-started.md ← Core concepts +└── README.md ← This overview +``` + +**Remember**: The complete workflow guide contains everything you need for 95% of Mix CMS development tasks. diff --git a/src/applications/mixcore/Controllers/InitController.cs b/src/applications/mixcore/Controllers/InitController.cs index d594c7911f..078312b0d5 100644 --- a/src/applications/mixcore/Controllers/InitController.cs +++ b/src/applications/mixcore/Controllers/InitController.cs @@ -38,18 +38,12 @@ public IActionResult Index(string page) } else { - if (string.IsNullOrEmpty(Configuration.AesKey())) - { - var newKey = AesEncryptionHelper.GenerateCombinedKeys(); - _appSettingsService.SetConfig("AesKey", newKey); - Configuration["AesKey"] = newKey; - } page ??= ""; switch (Configuration.InitStep()) { case InitStep.Blank: case InitStep.InitTenant: - InitEndpoints(); + InitialDefaultCmsConfiguration(); if (!string.IsNullOrEmpty(page.ToLower())) { return Redirect(InitRoutePath.Default); @@ -74,24 +68,21 @@ public IActionResult Index(string page) } break; } - _appSettingsService.SaveSettings(); return View(); } } - private void InitEndpoints() + private void InitialDefaultCmsConfiguration() { string endpoint = $"{Request.Scheme}://{Request.Host}"; + _appSettingsService.AppSettings.BaseUrl = endpoint; _appSettingsService.AppSettings.McpSettings.BaseUrl = $"{endpoint}/mcp/sse"; - _mixEndpointService.Messenger = endpoint; - _mixEndpointService.Portal = endpoint; - _mixEndpointService.Grpc = endpoint; - _mixEndpointService.Scheduler = endpoint; - _mixEndpointService.Theme = endpoint; - _mixEndpointService.Account = endpoint; - _mixEndpointService.Common = endpoint; - _mixEndpointService.Mixcore = endpoint; - _mixEndpointService.SaveSettings(); + _appSettingsService.SetConfig(nameof(AppSettingsModel.BaseUrl), endpoint); + if (string.IsNullOrEmpty(Configuration.AesKey())) + { + _appSettingsService.SetConfig("AesKey", AesEncryptionHelper.GenerateCombinedKeys()); + } + _appSettingsService.SaveSettings(); } } } diff --git a/src/applications/mixcore/Documents/ai-getting-started.md b/src/applications/mixcore/Documents/ai-getting-started.md new file mode 100644 index 0000000000..f99c53c109 --- /dev/null +++ b/src/applications/mixcore/Documents/ai-getting-started.md @@ -0,0 +1,220 @@ +Welcome! You are a **Mix AI Agent** designed to help build and manage websites using Mix CMS. This guide will walk you through the essential concepts and tools you'll need. + +## πŸ€– YOUR IDENTITY: MIX AI AGENT +**Critical Protocol**: You are a Mix AI Agent with these mandatory requirements: + +1. **Always Check MCP Server Support First** - Before any task, verify if Mix MCP Server can handle it +2. **Maintain Agent Identity** - Never lose your Mix AI Agent character during conversations +3. **Document MCP Usage** - Record which MCP tools were used and their effectiveness +4. **MCP First, Code Second** - Only use direct C# code when MCP tools are insufficient + +--- + +## Core Concepts: Building Blocks of Your Website + +Your website is made of two main things: **Templates** (the design and layout) and **Content** (the text and images). + +### Templates: The Blueprint for Your Pages + +Templates define how your content looks. Think of them as reusable blueprints. We have different types for different jobs: + +- **Master Layouts (`folderType: 7`):** The main skeleton of your site. This is where your site-wide header, footer, and navigation live. **Every page needs one.** +- **Page Templates (`folderType: 1`):** The layout for a specific type of page, like a blog post or a contact page. It defines the content area within the Master Layout. +- **Modules (`folderType: 2`):** Reusable blocks of content, like a contact form or an image gallery that can be placed on any page. + +#### Template Folder Types Reference + +The `folderType` parameter corresponds to the `MixTemplateFolderType` enum: + +```csharp +public enum MixTemplateFolderType +{ + Layouts = 0, // Layout templates + Pages = 1, // Page templates + Modules = 2, // Module templates + Forms = 3, // Form templates + Edms = 4, // Document management templates + Posts = 5, // Post/blog templates + Widgets = 6, // Widget templates + Masters = 7, // Master layout templates +} +``` + +**Most commonly used:** +- `folderType: 7` (Masters) - Master layouts +- `folderType: 1` (Pages) - Page templates +- `folderType: 2` (Modules) - Reusable modules +- `folderType: 5` (Posts) - Blog posts and articles + +### Content: The Information on Your Pages + +- **Pages (`CreatePageContent`):** The actual webpages that your visitors see, like "Home" or "About". Each page uses a Page Template to display its content. The `content` parameter should include HTML that will be rendered in the template. The Master Layout is automatically loaded by the CMS based on theme settings. +- **Posts (`CreatePostContent`):** Used for blog entries or news articles. The `content` parameter should include HTML for the post body that will be rendered in the template. The layout is automatically determined by the CMS. +- **Custom Data (`CreateDatabaseFromPrompt`):** For lists of things, like products, team members, or service offerings. Instead of hard-coding them into a page, you can store them in a database table and display them dynamically. + +--- + +## Your Toolbox: The MCP Commands + +As a **Mix AI Agent**, you have access to powerful MCP (Model Context Protocol) tools through Mix.Mcp.Services. **Always check MCP Server support first** before suggesting alternative approaches. + +### MCP Server Priority Protocol +1. **Check Available MCP Tools**: Use `GetTables()`, `ListTemplates()`, etc. to verify capabilities +2. **Use MCP Tools First**: Leverage Mix.Mcp.Services for all Mix CMS operations +3. **Document Usage**: Record which MCP tools were successful +4. **Note Limitations**: If MCP Server can't handle a task, document for future enhancement + +### For Managing Templates + +- `CreateTemplate`: Make a new template. +- `ListTemplates`: See all existing templates. +- `UpdateTemplate`: Change an existing template. +- `DeleteTemplate`: Remove a template. + +### For Managing Content + +- `CreatePageContent`: Create a new webpage. +- `CreatePostContent`: Create a new blog post or article. +- `CreateModuleContent`: Create a new reusable module. +- `ListPageContents`: See all your pages. +- `ListPostContents`: See all your posts. +- `ListModuleContents`: See all your modules. +- `UpdatePageContent`: Change a page's content or settings. +- `UpdatePostContent`: Change a post's content or settings. +- `UpdateModuleContent`: Change a module's content or settings. +- `DeletePageContent`: Remove a page. +- `DeletePostContent`: Remove a post. +- `DeleteModuleContent`: Remove a module. + +### For Managing Data + +- `CreateDatabaseFromPrompt`: Create a new database table from a simple description. +- `CreateManyMixDbData`: Add multiple records (e.g., products, services) to a table at once. **Always use full, public URLs for images, photos, pictures, ...** (e.g., `https://images.unsplash.com/photo-...`). +- `GetListMidxDbData`: Fetch data from a table to display on a page. + +### For Managing Relationships + +- `CreateMixDbRelationshipFromPrompt`: Create relationships between different content types (e.g., pages with modules, posts with categories). +- **Use Cases:** Connect pages with nested modules, organize posts by categories, create content hierarchies. +- **Important:** Always use `loadNestedData: true` when querying content with relationships. + +--- + +## Getting Started Resources + +Now that you understand the basics, here are the next steps: + +### πŸ“š **Step-by-Step Guides** +- **[Creating Basic Pages](./ai-workflows-basic-pages.md)** - Learn how to create webpages, templates, and layouts +- **[Creating Basic Modules](./ai-workflows-basic-modules.md)** - Learn how to create and manage reusable modules +- **[Working with Dynamic Data](./ai-workflows-dynamic-data.md)** - Handle databases, modules, and data-driven content +- **[Creating Blog Posts](./ai-workflows-posts.md)** - Set up blog posts and news articles +- **[Creating Database Relationships](./ai-workflows-relationships.md)** - Learn when and how to create relationships between content types + +### πŸ› οΈ **Technical References** +- **[Template Patterns & Best Practices](./patterns/template-patterns-overview.md)** - Template code patterns, rendering, and troubleshooting +- **[Mix CMS Reference](./reference/mix-cms-reference.md)** - Enums, constants, and technical reference guide +- **[MCP Tools Reference](./reference/mcp-tools-reference.md)** - Complete MCP command documentation and enhanced agentic server architecture + +### πŸ“– **Additional Resources** +- **[Developer Guide](./developer-guide.md)** - Technical guide for C# developers +- **[Website Building Best Practices](./website-building-best-practices.md)** - Project workflow and methodology +- **[MixDb Lessons Learned](./mixdb-lessons-learned.md)** - Database best practices and common pitfalls + +--- + +## Key Development Patterns + +### Service Usage (Critical) +- **Data Access:** Use `IMixDbDataServiceFactory` with dependency injection +- **Field Access:** Use typed methods: `@(item.Value("fieldName"))` +- **Required Setup:** Include namespaces and inject services +- **Query Pattern:** Use `SearchMixDbRequestModel` for data queries +- **Template Models:** Use correct model based on template type: + - Pages: `@model Mixcore.Domain.ViewModels.PageContentViewModel` + - Posts: `@model Mixcore.Domain.ViewModels.PostContentViewModel` + - Modules: `@model Mixcore.Domain.ViewModels.ModuleContentViewModel` or `@model dynamic` + - Database-driven: `@model dynamic` + +### Template Structure +```razor +@using Mix.Mixdb.Interfaces +@using Mix.Shared.Models +@using Mix.Shared.Dtos +@using Mix.Constant.Enums +@using Mix.Constant.Constants + +@inject Mix.Database.Services.MixGlobalSettings.DatabaseService dbSrv; +@inject IMixDbDataServiceFactory mixDbDataServiceFactory + +@{ + var mixDbDataService = mixDbDataServiceFactory.Create(dbSrv.DatabaseProvider, dbSrv.GetConnectionString(MixConstants.CONST_CMS_CONNECTION)); + var request = new SearchMixDbRequestModel + { + TableName = "table_name", + Queries = new List() + }; + var items = await mixDbDataService.GetListByAsync(request); +} + +@foreach (var item in items) +{ +
@(item.Value("name"))
+} +``` + +### Partial Rendering +- Use relative paths: `"../Modules/TemplateName.cshtml"` (must start with "../" and end with ".cshtml") +- Follow enum pattern: `$"../{template.FolderType.ToString()}/FileName.cshtml"` + +### Task Documentation (CRITICAL) +**After every successful task execution, you MUST document it in markdown files:** +- Update `database-schema.md` for any database changes +- Update `project-progress.md` for completed features +- Include date, description, status, and notes for team collaboration +- This ensures others can work in the same context and build upon your work + +--- + +## Quick Start Checklist + +βœ… **Before you begin:** +1. Understand the difference between Templates (design) and Content (information) +2. Know that every page needs a Master Layout +3. Remember that dynamic data should use database tables, not hard-coded content + +βœ… **Your first website:** +1. Create a Master Layout template (`folderType: 7`) +2. Create a Page Template (`folderType: 1`) +3. Create your first page content that uses the page template (layout is automatically assigned by CMS) + +βœ… **Next steps:** +1. Add dynamic content using database tables +2. Create reusable modules for common components +3. Set up blog posts if needed +4. Create relationships between content types when building complex layouts +5. Use the MCP Tools for CRUD operations on all content types + +--- + +## Important Notes for Complex Websites + +### When to Use Relationships +- **Page-Module Relationships:** When pages need multiple nested modules (header, hero, content, footer) +- **Post-Category Relationships:** When organizing blog content by topics or tags +- **Custom Content Relationships:** When connecting business data (e.g., appointments to services) + +### MCP Tools Best Practices +- Always check existing templates with `ListTemplates` before creating new ones +- Use `loadNestedData: true` when querying content with relationships +- Document all relationships in `database-schema.md` and `project-progress.md` +- Follow the proper `folderType` values for template creation + +--- + +## Need Help? + +- **Troubleshooting:** Check the [Template Patterns & Best Practices](./patterns/template-patterns-overview.md) guide +- **Relationships:** Consult [Creating Database Relationships](./ai-workflows-relationships.md) for complex content connections +- **Command Reference:** Use [MCP Tools Reference](./reference/mcp-tools-reference.md) for specific tool parameters +- **Technical Issues:** Consult the [Developer Guide](./reference/developer-guide.md) for advanced topics diff --git a/src/applications/mixcore/Domain/Extensions/ServiceExtension.cs b/src/applications/mixcore/Domain/Extensions/ServiceExtension.cs index 0a483c93f9..e2aa90ff21 100644 --- a/src/applications/mixcore/Domain/Extensions/ServiceExtension.cs +++ b/src/applications/mixcore/Domain/Extensions/ServiceExtension.cs @@ -1,9 +1,12 @@ -ο»Ώusing Newtonsoft.Json.Converters; +ο»Ώusing Mix.Portal.Domain.Services; +using Newtonsoft.Json.Converters; namespace Microsoft.Extensions.DependencyInjection { public static class ServiceExtension { + static string notStartWith = "mixmq\\.MixMq|admin|hub|mqtt|mcp|metrics|mixcontent|mix-app|graph|app|init|page|post|security|portal|api|vue|error|swagger|graphql|ReDoc|OpenAPI|.+Hub"; + static string notEndWith = "jpg|jpeg|png|gif|bmp|pdf|docx?|xlsx?|pptx?|txt|csv|exe|zip|rar|json|js|css|webmanifest|ico|svg|webm|mp3|mp4|wmv|otf|ttf"; #region Routes public static void AddMixRoutes(this IServiceCollection services) @@ -15,15 +18,15 @@ public static void AddMixRoutes(this IServiceCollection services) { options.SerializerSettings.Converters.Add(new StringEnumConverter()); }); - + services.AddScoped(); services.AddSingleton(); } public static void UseMixMVCEndpoints(this IEndpointRouteBuilder routes) { - string notStartWithPattern = "regex(^(?!(metrics|mixcontent|mix-app|graph|app|init|page|post|security|portal|api|vue|error|swagger|graphql|ReDoc|OpenAPI|.+Hub))(.+)$)"; + string notStartWithPattern = $"regex(^(?!\\/?({notStartWith})(\\/|$))(?!.*\\.({notEndWith})$).+$)"; //string urlPathPattern = @"regex((([A-z0-9\-\%]+\/)*[A-z0-9\-\%]+$)?)"; - + routes.MapDynamicControllerRoute( pattern: "{seoName:" + notStartWithPattern + "}"); routes.MapDynamicControllerRoute( diff --git a/src/applications/mixcore/Domain/Services/PostService.cs b/src/applications/mixcore/Domain/Services/MixcorePostService.cs similarity index 100% rename from src/applications/mixcore/Domain/Services/PostService.cs rename to src/applications/mixcore/Domain/Services/MixcorePostService.cs diff --git a/src/applications/mixcore/Views/Post/Index.cshtml b/src/applications/mixcore/Views/Post/Index.cshtml index 01fc43e73b..36ef6f1714 100644 --- a/src/applications/mixcore/Views/Post/Index.cshtml +++ b/src/applications/mixcore/Views/Post/Index.cshtml @@ -1,7 +1,7 @@ ο»Ώ@model Mixcore.Domain.ViewModels.PostContentViewModel @{ - Layout = Model.Layout.FilePath; ViewData["Title"] = Model.SeoTitle; + Layout = Model.Layout?.FilePath; } diff --git a/src/applications/mixcore/appsettings.json b/src/applications/mixcore/appsettings.json index c99a85e779..e7d853bbcf 100644 --- a/src/applications/mixcore/appsettings.json +++ b/src/applications/mixcore/appsettings.json @@ -15,7 +15,7 @@ "HttpScheme": "https", "DatabaseProvider": "SQLITE", "IsInit": true, - "AesKey": "RHhjdXVHZmFpSVlmZmdhcHdNNFVQUT09LEIvN0FGTXB3MEM4TnZSbXdCSC9LT0s4STJ4ZUFSSFNpRnQzTzh4Y3BkSVE9", + "AesKey": null, "LlmServiceOptions": { "DeepSeek": { "BaseUrl": "https://api.deepseek.com/v1", diff --git a/src/applications/mixcore/wwwroot/default-mixcontent/default.zip b/src/applications/mixcore/wwwroot/default-mixcontent/default.zip index dedee38711..0a48a02a77 100644 Binary files a/src/applications/mixcore/wwwroot/default-mixcontent/default.zip and b/src/applications/mixcore/wwwroot/default-mixcontent/default.zip differ diff --git a/src/applications/mixcore/wwwroot/mix-app/js/app-init.min.js b/src/applications/mixcore/wwwroot/mix-app/js/app-init.min.js index ca6401c47b..3a8ed65a2b 100644 --- a/src/applications/mixcore/wwwroot/mix-app/js/app-init.min.js +++ b/src/applications/mixcore/wwwroot/mix-app/js/app-init.min.js @@ -195,6 +195,72 @@ app.factory("Step1Services", [ }, ]); +"use strict"; +app.controller("Step4Controller", [ + "$scope", + "$rootScope", + "ApiService", + "AuthService", + "Step4Services", + function ($scope, $rootScope, apiService, authService, service) { + $scope.importThemeDto = null; + $scope.canContinue = true; + $scope.data = []; + $scope.init = async function () { + await apiService.getGlobalSettings(); + var getData = await service.loadTheme(); + if (getData.success) { + $scope.importThemeDto = getData.data; + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.submit = async function (event) { + $rootScope.isBusy = true; + var result = await service.submit(event, $scope.importThemeDto); + if (result.success) { + window.top.location = "/admin"; + } else { + if (result) { + $rootScope.showErrors(result.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + }, +]); + +"use strict"; +app.factory("Step4Services", [ + "ApiService", + "CommonService", + function (apiService, commonService) { + var service = {}; + + var _loadTheme = async function () { + var req = { + method: "GET", + url: "/rest/mix-tenancy/setup/load-theme", + }; + return await apiService.sendRequest(req); + }; + var _submit = async function (event, data) { + var req = { + method: "POST", + url: "/rest/mix-tenancy/setup/import-theme", + data: JSON.stringify(data), + transformRequest: angular.identity, // Important for FormData + event: event, + }; + return await apiService.sendRequest(req); + }; + service.loadTheme = _loadTheme; + service.submit = _submit; + return service; + }, +]); + "use strict"; app.controller("Step2Controller", [ "$scope", @@ -459,7 +525,7 @@ app.controller("Step5Controller", [ var result = await service.submit($scope.data); if (result.success) { $rootScope.isBusy = false; - window.top.location = "/"; + window.top.location = "/admin"; } else { if (result) { $rootScope.showErrors(result.errors); @@ -491,72 +557,6 @@ app.factory("Step5Services", [ }, ]); -"use strict"; -app.controller("Step4Controller", [ - "$scope", - "$rootScope", - "ApiService", - "AuthService", - "Step4Services", - function ($scope, $rootScope, apiService, authService, service) { - $scope.importThemeDto = null; - $scope.canContinue = true; - $scope.data = []; - $scope.init = async function () { - await apiService.getGlobalSettings(); - var getData = await service.loadTheme(); - if (getData.success) { - $scope.importThemeDto = getData.data; - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.submit = async function (event) { - $rootScope.isBusy = true; - var result = await service.submit(event, $scope.importThemeDto); - if (result.success) { - window.top.location = "/"; - } else { - if (result) { - $rootScope.showErrors(result.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - }, -]); - -"use strict"; -app.factory("Step4Services", [ - "ApiService", - "CommonService", - function (apiService, commonService) { - var service = {}; - - var _loadTheme = async function () { - var req = { - method: "GET", - url: "/rest/mix-tenancy/setup/load-theme", - }; - return await apiService.sendRequest(req); - }; - var _submit = async function (event, data) { - var req = { - method: "POST", - url: "/rest/mix-tenancy/setup/import-theme", - data: JSON.stringify(data), - transformRequest: angular.identity, // Important for FormData - event: event, - }; - return await apiService.sendRequest(req); - }; - service.loadTheme = _loadTheme; - service.submit = _submit; - return service; - }, -]); - modules.component("mssqlInfo", { templateUrl: "/mix-app/views/app-init/pages/step1/components/mssql-info/view.html", @@ -568,261 +568,62 @@ modules.component("mssqlInfo", { ], bindings: { initCmsModel: "=", - }, -}); - -modules.component("mssqlLocalInfo", { - templateUrl: - "/mix-app/views/app-init/pages/step1/components/mssql-local-info/view.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - }, - ], - bindings: { - initCmsModel: "=", - }, -}); - -modules.component("mysqlInfo", { - templateUrl: - "/mix-app/views/app-init/pages/step1/components/mysql-info/view.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - }, - ], - bindings: { - initCmsModel: "=", - }, -}); - -modules.component("posgresqlInfo", { - templateUrl: - "/mix-app/views/app-init/pages/step1/components/posgresql-info/view.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - }, - ], - bindings: { - initCmsModel: "=", - }, -}); - -modules.component("sqliteInfo", { - templateUrl: - "/mix-app/views/app-init/pages/step1/components/sqlite-info/view.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - }, - ], - bindings: { - initCmsModel: "=", - }, -}); - -app.component("initGgConfigurations", { - templateUrl: - "/mix-app/views/app-init/pages/step3/components/gg-configurations/view.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - ctrl.data = []; - ctrl.$onInit = function () { - ctrl.data = $rootScope.filterArray( - ctrl.configurations, - ["category"], - ["Social_Google"] - ); - }; - }, - ], - bindings: { - configurations: "=", - }, -}); - -modules.component("initValueEditor", { - templateUrl: - "/mix-app/views/app-init/pages/step3/components/init-value-editor/view.html", - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - "FileService", - function ($rootScope, $scope, ngAppSettings, fileService) { - var ctrl = this; - ctrl.icons = ngAppSettings.icons; - ctrl.mediaFile = { - file: null, - fullPath: "", - fileFolder: "content/site", - title: "", - description: "", - }; - this.dataTypes = ngAppSettings.dataTypes; - ctrl.initEditor = function () { - ctrl.data.value = ctrl.data.default || null; - setTimeout(function () { - // Init Code editor - $.each($(".code-editor"), function (i, e) { - var container = $(this); - var editor = ace.edit(e); - if (container.hasClass("json")) { - editor.session.setMode("ace/mode/json"); - } else { - editor.session.setMode("ace/mode/razor"); - } - editor.setTheme("ace/theme/chrome"); - //editor.setReadOnly(true); - - editor.session.setUseWrapMode(true); - editor.setOptions({ - maxLines: Infinity, - }); - editor.getSession().on("change", function (e) { - // e.type, etc - $(container) - .parent() - .find(".code-content") - .val(editor.getValue()); - }); - }); - $.each($(".editor-content"), function (i, e) { - var $demoTextarea = $(e); - $demoTextarea - .trumbowyg({ - semantic: false, - }) - .on("tbwblur", function () { - ctrl.data.value = $demoTextarea.val(); - }); - }); - }, 200); - }; - ctrl.selectFile = function (file, errFiles) { - if (file !== undefined && file !== null) { - ctrl.mediaFile.folder = ctrl.folder ? ctrl.folder : "Media"; - ctrl.mediaFile.title = ctrl.title ? ctrl.title : ""; - ctrl.mediaFile.description = ctrl.description ? ctrl.description : ""; - ctrl.mediaFile.file = file; - - ctrl.uploadFile(file); - } - }; - ctrl.uploadFile = async function (file) { - if (file !== null) { - $rootScope.isBusy = true; - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = async function () { - ctrl.mediaFile.fileName = file.name.substring( - 0, - file.name.lastIndexOf(".") - ); - ctrl.mediaFile.extension = file.name.substring( - file.name.lastIndexOf(".") - ); - ctrl.mediaFile.fileBase64 = reader.result; - var resp = await fileService.save(ctrl.mediaFile); - if (resp && resp.success) { - ctrl.data.value = resp.data.webPath; - ctrl.srcUrl = resp.data.webPath; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - reader.onerror = function (error) {}; - } else { - return null; - } - }; + }, +}); + +modules.component("mssqlLocalInfo", { + templateUrl: + "/mix-app/views/app-init/pages/step1/components/mssql-local-info/view.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; }, ], bindings: { - data: "=", - inputClass: "=", - isShowTitle: "=", - title: "=", + initCmsModel: "=", }, }); -app.component("initSiteConfigurations", { +modules.component("mysqlInfo", { templateUrl: - "/mix-app/views/app-init/pages/step3/components/site-configurations/view.html", + "/mix-app/views/app-init/pages/step1/components/mysql-info/view.html", controller: [ "$rootScope", function ($rootScope) { var ctrl = this; - ctrl.data = []; - ctrl.$onInit = function () { - ctrl.data = $rootScope.filterArray( - ctrl.configurations, - ["category"], - ["Site_Common"] - ); - }; }, ], bindings: { - configurations: "=", + initCmsModel: "=", }, }); -app.component("initFbConfigurations", { +modules.component("sqliteInfo", { templateUrl: - "/mix-app/views/app-init/pages/step3/components/fb-configurations/view.html", + "/mix-app/views/app-init/pages/step1/components/sqlite-info/view.html", controller: [ "$rootScope", function ($rootScope) { var ctrl = this; - ctrl.data = []; - ctrl.$onInit = function () { - ctrl.data = $rootScope.filterArray( - ctrl.configurations, - ["category"], - ["Social_Facebook"] - ); - }; }, ], bindings: { - configurations: "=", + initCmsModel: "=", }, }); -app.component("initSysConfigurations", { +modules.component("posgresqlInfo", { templateUrl: - "/mix-app/views/app-init/pages/step3/components/site-configurations/view.html", + "/mix-app/views/app-init/pages/step1/components/posgresql-info/view.html", controller: [ "$rootScope", function ($rootScope) { var ctrl = this; - ctrl.data = []; - ctrl.$onInit = function () { - ctrl.data = $rootScope.filterArray( - ctrl.configurations, - ["category"], - ["System"] - ); - }; }, ], bindings: { - configurations: "=", + initCmsModel: "=", }, }); @@ -1205,3 +1006,202 @@ app.component("themeImportPosts", { importThemeDto: "=", }, }); + +app.component("initFbConfigurations", { + templateUrl: + "/mix-app/views/app-init/pages/step3/components/fb-configurations/view.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.data = []; + ctrl.$onInit = function () { + ctrl.data = $rootScope.filterArray( + ctrl.configurations, + ["category"], + ["Social_Facebook"] + ); + }; + }, + ], + bindings: { + configurations: "=", + }, +}); + +app.component("initSiteConfigurations", { + templateUrl: + "/mix-app/views/app-init/pages/step3/components/site-configurations/view.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.data = []; + ctrl.$onInit = function () { + ctrl.data = $rootScope.filterArray( + ctrl.configurations, + ["category"], + ["Site_Common"] + ); + }; + }, + ], + bindings: { + configurations: "=", + }, +}); + +modules.component("initValueEditor", { + templateUrl: + "/mix-app/views/app-init/pages/step3/components/init-value-editor/view.html", + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "FileService", + function ($rootScope, $scope, ngAppSettings, fileService) { + var ctrl = this; + ctrl.icons = ngAppSettings.icons; + ctrl.mediaFile = { + file: null, + fullPath: "", + fileFolder: "content/site", + title: "", + description: "", + }; + this.dataTypes = ngAppSettings.dataTypes; + ctrl.initEditor = function () { + ctrl.data.value = ctrl.data.default || null; + setTimeout(function () { + // Init Code editor + $.each($(".code-editor"), function (i, e) { + var container = $(this); + var editor = ace.edit(e); + if (container.hasClass("json")) { + editor.session.setMode("ace/mode/json"); + } else { + editor.session.setMode("ace/mode/razor"); + } + editor.setTheme("ace/theme/chrome"); + //editor.setReadOnly(true); + + editor.session.setUseWrapMode(true); + editor.setOptions({ + maxLines: Infinity, + }); + editor.getSession().on("change", function (e) { + // e.type, etc + $(container) + .parent() + .find(".code-content") + .val(editor.getValue()); + }); + }); + $.each($(".editor-content"), function (i, e) { + var $demoTextarea = $(e); + $demoTextarea + .trumbowyg({ + semantic: false, + }) + .on("tbwblur", function () { + ctrl.data.value = $demoTextarea.val(); + }); + }); + }, 200); + }; + ctrl.selectFile = function (file, errFiles) { + if (file !== undefined && file !== null) { + ctrl.mediaFile.folder = ctrl.folder ? ctrl.folder : "Media"; + ctrl.mediaFile.title = ctrl.title ? ctrl.title : ""; + ctrl.mediaFile.description = ctrl.description ? ctrl.description : ""; + ctrl.mediaFile.file = file; + + ctrl.uploadFile(file); + } + }; + ctrl.uploadFile = async function (file) { + if (file !== null) { + $rootScope.isBusy = true; + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = async function () { + ctrl.mediaFile.fileName = file.name.substring( + 0, + file.name.lastIndexOf(".") + ); + ctrl.mediaFile.extension = file.name.substring( + file.name.lastIndexOf(".") + ); + ctrl.mediaFile.fileBase64 = reader.result; + var resp = await fileService.save(ctrl.mediaFile); + if (resp && resp.success) { + ctrl.data.value = resp.data.webPath; + ctrl.srcUrl = resp.data.webPath; + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + reader.onerror = function (error) {}; + } else { + return null; + } + }; + }, + ], + bindings: { + data: "=", + inputClass: "=", + isShowTitle: "=", + title: "=", + }, +}); + +app.component("initGgConfigurations", { + templateUrl: + "/mix-app/views/app-init/pages/step3/components/gg-configurations/view.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.data = []; + ctrl.$onInit = function () { + ctrl.data = $rootScope.filterArray( + ctrl.configurations, + ["category"], + ["Social_Google"] + ); + }; + }, + ], + bindings: { + configurations: "=", + }, +}); + +app.component("initSysConfigurations", { + templateUrl: + "/mix-app/views/app-init/pages/step3/components/site-configurations/view.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.data = []; + ctrl.$onInit = function () { + ctrl.data = $rootScope.filterArray( + ctrl.configurations, + ["category"], + ["System"] + ); + }; + }, + ], + bindings: { + configurations: "=", + }, +}); diff --git a/src/applications/mixcore/wwwroot/mix-app/js/app-portal.min.js b/src/applications/mixcore/wwwroot/mix-app/js/app-portal.min.js index 45bd7d0bfc..73aa707633 100644 --- a/src/applications/mixcore/wwwroot/mix-app/js/app-portal.min.js +++ b/src/applications/mixcore/wwwroot/mix-app/js/app-portal.min.js @@ -1,4 +1,4 @@ -/* Wed Jun 25 2025 17:15:26 GMT+0700 (Indochina Time) */"use strict"; +/* Wed Jul 30 2025 17:29:19 GMT+0700 (Indochina Time) */"use strict"; var app = angular.module("MixPortal", [ "angularCroppie", "ui.bootstrap", @@ -563,89 +563,6 @@ app.factory("MixApplicationRestService", [ }, ]); -"use strict"; -app.controller("CultureController", [ - "$scope", - "$rootScope", - "ngAppSettings", - "$routeParams", - "CultureService", - "CommonService", - "ApiService", - function ( - $scope, - $rootScope, - ngAppSettings, - $routeParams, - service, - commonService, - apiService - ) { - $scope.selected = null; - BaseCtrl.call( - this, - $scope, - $rootScope, - $routeParams, - ngAppSettings, - service - ); - $scope.loadCultures = async function () { - var getCultures = await commonService.loadJsonData("cultures"); - $scope.cultures = getCultures.data.items; - $scope.$apply(); - }; - $scope.saveSuccessCallback = function () { - apiService - .initAllSettings() - .then(() => (window.location.href = "/admin/language/list")); - }; - $scope.removeCallback = function () { - apiService - .initAllSettings() - .then(() => (window.location.href = "/admin/language/list")); - }; - $scope.changeData = function (selected) { - if (selected) { - $scope.viewmodel.specificulture = selected.specificulture; - $scope.viewmodel.displayName = selected.fullName; - $scope.viewmodel.icon = selected.icon; - } - }; - }, -]); - -"use strict"; -app.factory("CultureService", [ - "BaseRestService", - function (baseService) { - var serviceFactory = Object.create(baseService); - serviceFactory.init("culture"); - var _updateInfos = async function (pages) { - var req = { - method: "POST", - url: this.prefixUrl + "/update-infos", - data: JSON.stringify(pages), - }; - return await apiService.sendRequest(req); - }; - - var _syncTemplates = async function (id) { - var apiUrl = "/culture/"; - var url = apiUrl + "sync/" + id; - var req = { - method: "GET", - url: url, - }; - return await apiService.sendRequest(req); - }; - - serviceFactory.syncTemplates = _syncTemplates; - serviceFactory.updateInfos = _updateInfos; - return serviceFactory; - }, -]); - "use strict"; app.controller("AuditLogController", [ "$scope", @@ -785,150 +702,97 @@ app.factory("AuditLogRestService", [ ]); "use strict"; -app.controller("DomainController", [ +app.controller("CultureController", [ "$scope", "$rootScope", "ngAppSettings", - "$location", "$routeParams", - "DomainRestService", + "CultureService", + "CommonService", + "ApiService", function ( $scope, $rootScope, ngAppSettings, - $location, $routeParams, - service + service, + commonService, + apiService ) { - BaseRestCtrl.call( + $scope.selected = null; + BaseCtrl.call( this, $scope, $rootScope, - $location, $routeParams, ngAppSettings, service ); - $scope.request.columns = [ - "id", - "displayName", - "host", - "createdDateTime", - "createdBy", - ]; - $scope.canDrag = - $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; + $scope.loadCultures = async function () { + var getCultures = await commonService.loadJsonData("cultures"); + $scope.cultures = getCultures.data.items; + $scope.$apply(); + }; + $scope.saveSuccessCallback = function () { + apiService + .initAllSettings() + .then(() => (window.location.href = "/admin/language/list")); + }; + $scope.removeCallback = function () { + apiService + .initAllSettings() + .then(() => (window.location.href = "/admin/language/list")); + }; + $scope.changeData = function (selected) { + if (selected) { + $scope.viewmodel.specificulture = selected.specificulture; + $scope.viewmodel.displayName = selected.fullName; + $scope.viewmodel.icon = selected.icon; + } + }; }, ]); "use strict"; -app.factory("DomainRestService", [ +app.factory("CultureService", [ "BaseRestService", function (baseService) { var serviceFactory = Object.create(baseService); - serviceFactory.init("mix-domain"); - return serviceFactory; - }, -]); - -"use strict"; -app.controller("DashboardController", [ - "$scope", - "$rootScope", - "ngAppSettings", - "$timeout", - "$location", - "DashboardServices", - "AuthService", - function ( - $scope, - $rootScope, - ngAppSettings, - $timeout, - $location, - dashboardServices, - authService - ) { - var endpoints = JSON.parse(localStorage.getItem("ls.endpoints") || "{}"); - BaseHub.call(this, $scope, endpoints.OneApp); - $scope.pageClass = "page-dashboard"; - $(".side-nav li").removeClass("active"); - $(".side-nav .page-dashboard").addClass("active"); - $scope.data = { - totalPage: 0, - totalPost: 0, - totalProduct: 0, - totalUser: 0, - }; - $scope.users = []; - $scope.$on("$viewContentLoaded", function () { - $rootScope.isBusy = false; - }); - $scope.init = async function () {}; - $scope.receiveMessage = (msg) => { - console.log(msg); - $scope.result = msg; - $scope.$apply(); - $rootScope.showMessage(msg.title, $scope.getMessageType(msg.type)); - }; - - $scope.getChart = function () { - var ctx = document.getElementById("myChart"); - var myChart = new Chart(ctx, { - // type: 'pie', - // data: { - // labels: ["Africa", "Asia", "Europe", "Latin America", "North America"], - // datasets: [{ - // label: "Population (millions)", - // backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"], - // data: [2478,5267,734,784,433] - // }] - // }, - // options: { - // title: { - // display: true, - // text: 'Predicted world population (millions) in 2050' - // } - // } - }); + serviceFactory.init("culture"); + var _updateInfos = async function (pages) { + var req = { + method: "POST", + url: this.prefixUrl + "/update-infos", + data: JSON.stringify(pages), + }; + return await apiService.sendRequest(req); }; - }, -]); - -"use strict"; -app.factory("DashboardServices", [ - "$rootScope", - "$http", - "ApiService", - "CommonService", - function ($rootScope, $http, apiService, commonService) { - //var serviceBase = 'http://ngauthenticationapi.azurewebsites.net/'; - var usersServiceFactory = {}; - var apiUrl = "/rest/portal/common/" + $rootScope.globalSettings.lang; - var _getDashboardInfo = async function () { + var _syncTemplates = async function (id) { + var apiUrl = "/culture/"; + var url = apiUrl + "sync/" + id; var req = { method: "GET", - url: apiUrl + "/dashboard", + url: url, }; return await apiService.sendRequest(req); }; - usersServiceFactory.getDashboardInfo = _getDashboardInfo; - return usersServiceFactory; + serviceFactory.syncTemplates = _syncTemplates; + serviceFactory.updateInfos = _updateInfos; + return serviceFactory; }, ]); "use strict"; -app.controller("FileController", [ +app.controller("CustomerController", [ "$scope", "$rootScope", "ngAppSettings", "$routeParams", "$timeout", "$location", - "AuthService", - "FileServices", + "CustomerServices", function ( $scope, $rootScope, @@ -936,23 +800,13 @@ app.controller("FileController", [ $routeParams, $timeout, $location, - authService, - fileServices + customerServices ) { - $scope.request = { - pageSize: "10", - pageIndex: 0, - status: "Published", - sortBy: "Id", - direction: "Desc", - fromDate: null, - toDate: null, - keyword: "", - key: "", - }; - - $scope.activedFile = null; - $scope.relatedFiles = []; + $scope.request = angular.copy(ngAppSettings.request); + $scope.request.contentStatuses = ["Active"]; + $scope.request.status = "0"; + $scope.activedCustomer = null; + $scope.relatedCustomers = []; $rootScope.isBusy = false; $scope.data = { pageIndex: 0, @@ -966,25 +820,14 @@ app.controller("FileController", [ for (var i = 1; i <= max; i += 1) input.push(i); return input; }; - $scope.loadPage = async function (folder) { - if (folder) { - $scope.request.folder += $scope.request.folder !== "" ? "/" : ""; - $scope.request.folder += folder; - } - $location.url( - "/admin/file/list?folder=" + encodeURIComponent($scope.request.folder) - ); - }; - $scope.loadFile = async function () { - $rootScope.isBusy = true; - $scope.listUrl = "/admin/file/list?folder/" + $routeParams.folder; + + $scope.loadCustomer = async function () { $rootScope.isBusy = true; - var response = await fileServices.getFile( - $routeParams.folder, - $routeParams.filename - ); + var id = $routeParams.id; + var response = await customerServices.getCustomer(id, "portal"); if (response.success) { - $scope.activedFile = response.data; + $scope.activedCustomer = response.data; + $rootScope.initEditor(); $rootScope.isBusy = false; $scope.$apply(); } else { @@ -993,34 +836,26 @@ app.controller("FileController", [ $scope.$apply(); } }; - $scope.loadFiles = async function (folder) { - if (folder) { - $scope.request.folder += - $scope.request.folder !== "" - ? "MixContent/StaticFiles" - : "MixContent/StaticFiles"; - $scope.request.folder += folder; - } else { - $scope.request.folder = $routeParams.folder - ? $routeParams.folder - : "MixContent/StaticFiles"; + $scope.loadCustomers = async function (pageIndex) { + if (pageIndex !== undefined) { + $scope.request.pageIndex = pageIndex; } - if ($routeParams.folder) { - $scope.backUrl = - "/admin/file/list?folder=" + - $routeParams.folder.substring( - 0, - $routeParams.folder.lastIndexOf("/") - ); + if ($scope.request.fromDate !== null) { + var d = new Date($scope.request.fromDate); + $scope.request.fromDate = d.toISOString(); } - $rootScope.isBusy = true; - var resp = await fileServices.getFiles($scope.request); + if ($scope.request.toDate !== null) { + var d = new Date($scope.request.toDate); + $scope.request.toDate = d.toISOString(); + } + var resp = await customerServices.getCustomers($scope.request); if (resp && resp.success) { $scope.data = resp.data; - $.each($scope.data.items, function (i, file) { - $.each($scope.activedFiles, function (i, e) { - if (e.fileId === file.id) { - file.isHidden = true; + //$("html, body").animate({ "scrollTop": "0px" }, 500); + $.each($scope.data.items, function (i, customer) { + $.each($scope.activedCustomers, function (i, e) { + if (e.customerId === customer.id) { + customer.isHidden = true; } }); }); @@ -1030,62 +865,71 @@ app.controller("FileController", [ if (resp) { $rootScope.showErrors(resp.errors); } - $rootScope.isBusy = false; $scope.$apply(); } }; - $scope.removeFile = async function (id) { - if (confirm("Are you sure!")) { - $rootScope.isBusy = true; - var resp = await fileServices.removeFile(id); - if (resp && resp.success) { - $scope.loadFiles(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); - } + $scope.removeCustomer = function (id) { + $rootScope.showConfirm( + $scope, + "removeCustomerConfirmed", + [id], + null, + "Remove Customer", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + + $scope.removeCustomerConfirmed = async function (id) { + var result = await customerServices.removeCustomer(id); + if (result.success) { + $rootScope.showMessage("success", "success"); + $scope.loadCustomers(); + } else { + $rootScope.showMessage("failed"); + $rootScope.isBusy = false; + $scope.$apply(); } }; - $scope.saveFile = async function (file) { - $rootScope.isBusy = true; - var resp = await fileServices.saveFile(file); + $scope.saveCustomer = async function (customer) { + customer.content = $(".editor-content").val(); + var resp = await customerServices.saveCustomer(customer); if (resp && resp.success) { - $scope.activedFile = resp.data; + $scope.activedCustomer = resp.data; $rootScope.showMessage("Update successfully!", "success"); $rootScope.isBusy = false; $scope.$apply(); + //$location.path('/admin/customer/details/' + resp.data.id); } else { if (resp) { $rootScope.showErrors(resp.errors); } - $rootScope.isBusy = false; $scope.$apply(); } }; - $scope.updateTemplateContent = function (content) { - $scope.activedFile.content = content; - }; }, ]); "use strict"; -app.factory("FileServices", [ +app.factory("CustomerServices", [ "$http", "$rootScope", "ApiService", "CommonService", - "BaseRestService", - function ($http, $rootScope, apiService, commonService, baseService) { - var filesServiceFactory = angular.copy(baseService); - filesServiceFactory.initService("/rest", "mix-storage/file-system", true); - var _getFile = async function (folder, filename) { - var url = - this.prefixUrl + "/details?folder=" + folder + "&filename=" + filename; + function ($http, $rootScope, apiService, commonService) { + //var serviceBase = 'http://ngauthenticationapi.azurewebsites.net/'; + + var customersServiceFactory = {}; + + var settings = $rootScope.globalSettings; + + var _getCustomer = async function (id, type) { + var apiUrl = "/queen-beauty/customer/"; + var url = apiUrl + "details/" + type; + if (id) { + url += "/" + id; + } var req = { method: "GET", url: url, @@ -1093,69 +937,51 @@ app.factory("FileServices", [ return await apiService.sendRequest(req); }; - var _initFile = async function (type) { + var _initCustomer = async function (type) { + var apiUrl = "/queen-beauty/customer/"; var req = { method: "GET", - url: this.prefixUrl + "/init/" + type, + url: apiUrl + "init/" + type, }; return await apiService.sendRequest(req); }; - var _getFiles = async function (request) { - var url = this.prefixUrl; - var data = filesServiceFactory.parseQuery(request); - if (data) { - url += "?"; - url = url.concat(data); - } + var _getCustomers = async function (request) { + var apiUrl = "/queen-beauty/customer/"; var req = { - method: "GET", - url: url, + method: "POST", + url: apiUrl + "list", data: JSON.stringify(request), }; + return await apiService.sendRequest(req); }; - var _removeFile = async function (fullPath) { + var _removeCustomer = async function (id) { + var apiUrl = "/queen-beauty/customer/"; var req = { - method: "DELETE", - url: this.prefixUrl + "/delete/?fullPath=" + fullPath, + method: "GET", + url: apiUrl + "delete/" + id, }; return await apiService.sendRequest(req); }; - var _saveFile = async function (file) { + var _saveCustomer = async function (customer) { + var apiUrl = "/queen-beauty/customer/"; var req = { method: "POST", - url: this.prefixUrl + "/save", - data: JSON.stringify(file), + url: apiUrl + "save", + data: JSON.stringify(customer), }; return await apiService.sendRequest(req); }; - var _uploadFile = async function (file, folder) { - var apiUrl = this.prefixUrl + "/upload-file"; - var fd = new FormData(); - fd.append("folder", folder); - fd.append("file", file); - return await filesServiceFactory.ajaxSubmitForm(fd, apiUrl); - }; - - var _extractFile = async function (file, folder) { - var apiUrl = this.prefixUrl + "/extract-file"; - var fd = new FormData(); - fd.append("folder", folder); - fd.append("file", file); - return await filesServiceFactory.ajaxSubmitForm(fd, apiUrl); - }; - filesServiceFactory.getFile = _getFile; - filesServiceFactory.initFile = _initFile; - filesServiceFactory.getFiles = _getFiles; - filesServiceFactory.removeFile = _removeFile; - filesServiceFactory.saveFile = _saveFile; - filesServiceFactory.uploadFile = _uploadFile; - filesServiceFactory.extractFile = _extractFile; - return filesServiceFactory; + customersServiceFactory.getCustomer = _getCustomer; + customersServiceFactory.initCustomer = _initCustomer; + customersServiceFactory.getCustomers = _getCustomers; + customersServiceFactory.removeCustomer = _removeCustomer; + customersServiceFactory.saveCustomer = _saveCustomer; + return customersServiceFactory; }, ]); @@ -1271,208 +1097,207 @@ app.factory("ConfigurationService", [ ]); "use strict"; -app.controller("CustomerController", [ +app.controller("DashboardController", [ "$scope", "$rootScope", "ngAppSettings", - "$routeParams", "$timeout", "$location", - "CustomerServices", + "$sce", + "DashboardServices", + "AuthService", function ( $scope, $rootScope, ngAppSettings, - $routeParams, $timeout, $location, - customerServices + $sce, + dashboardServices, + authService ) { - $scope.request = angular.copy(ngAppSettings.request); - $scope.request.contentStatuses = ["Active"]; - $scope.request.status = "0"; - $scope.activedCustomer = null; - $scope.relatedCustomers = []; - $rootScope.isBusy = false; + var endpoints = JSON.parse(localStorage.getItem("ls.endpoints") || "{}"); + BaseHub.call(this, $scope); + $scope.pageClass = "page-dashboard"; + $(".side-nav li").removeClass("active"); + $(".side-nav .page-dashboard").addClass("active"); $scope.data = { - pageIndex: 0, - pageSize: 1, - totalItems: 0, + totalPage: 0, + totalPost: 0, + totalProduct: 0, + totalUser: 0, }; - $scope.errors = []; - - $scope.range = function (max) { - var input = []; - for (var i = 1; i <= max; i += 1) input.push(i); - return input; + $scope.users = []; + $scope.$on("$viewContentLoaded", function () { + $rootScope.isBusy = false; + }); + $scope.init = async function () {}; + $scope.receiveMessage = (msg) => { + console.log(msg); + $scope.result = msg; + $scope.$apply(); + $rootScope.showMessage(msg.title, $scope.getMessageType(msg.type)); }; - $scope.loadCustomer = async function () { - $rootScope.isBusy = true; - var id = $routeParams.id; - var response = await customerServices.getCustomer(id, "portal"); - if (response.success) { - $scope.activedCustomer = response.data; - $rootScope.initEditor(); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.loadCustomers = async function (pageIndex) { - if (pageIndex !== undefined) { - $scope.request.pageIndex = pageIndex; - } - if ($scope.request.fromDate !== null) { - var d = new Date($scope.request.fromDate); - $scope.request.fromDate = d.toISOString(); - } - if ($scope.request.toDate !== null) { - var d = new Date($scope.request.toDate); - $scope.request.toDate = d.toISOString(); - } - var resp = await customerServices.getCustomers($scope.request); - if (resp && resp.success) { - $scope.data = resp.data; - //$("html, body").animate({ "scrollTop": "0px" }, 500); - $.each($scope.data.items, function (i, customer) { - $.each($scope.activedCustomers, function (i, e) { - if (e.customerId === customer.id) { - customer.isHidden = true; - } - }); - }); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $scope.$apply(); - } - }; - - $scope.removeCustomer = function (id) { - $rootScope.showConfirm( - $scope, - "removeCustomerConfirmed", - [id], - null, - "Remove Customer", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); + $scope.getChart = function () { + var ctx = document.getElementById("myChart"); + var myChart = new Chart(ctx, { + // type: 'pie', + // data: { + // labels: ["Africa", "Asia", "Europe", "Latin America", "North America"], + // datasets: [{ + // label: "Population (millions)", + // backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"], + // data: [2478,5267,734,784,433] + // }] + // }, + // options: { + // title: { + // display: true, + // text: 'Predicted world population (millions) in 2050' + // } + // } + }); }; + $scope.message = ""; + $scope.conversation = []; - $scope.removeCustomerConfirmed = async function (id) { - var result = await customerServices.removeCustomer(id); - if (result.success) { - $rootScope.showMessage("success", "success"); - $scope.loadCustomers(); + // For rendering markdown as HTML in the template + // Requires marked.js to be loaded globally. If not, will fallback to plain text. + $scope.trustAsHtml = function (html) { + if (typeof marked !== "undefined" && marked.parse) { + return $sce.trustAsHtml(marked.parse(html || "")); } else { - $rootScope.showMessage("failed"); - $rootScope.isBusy = false; - $scope.$apply(); + console.warn( + "marked.js is not loaded. Please include marked.min.js in your HTML." + ); + return $sce.trustAsHtml(html || ""); } }; - - $scope.saveCustomer = async function (customer) { - customer.content = $(".editor-content").val(); - var resp = await customerServices.saveCustomer(customer); - if (resp && resp.success) { - $scope.activedCustomer = resp.data; - $rootScope.showMessage("Update successfully!", "success"); - $rootScope.isBusy = false; - $scope.$apply(); - //$location.path('/admin/customer/details/' + resp.data.id); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); + // To enable markdown rendering, ensure you have included marked.min.js in your HTML: + // + $scope.askAI = function () { + $scope.connection.invoke("AskAI", $scope.message); + $scope.conversation.push({ + role: "user", + content: $scope.message, + }); + $scope.message = ""; + }; + $scope.startConnection( + "llm_chat", + authService.authentication.accessToken, + (err) => { + if ( + authService.authentication.refreshToken && + err.message.indexOf("401") >= 0 + ) { + authService.refreshToken().then(async () => { + $scope.startConnection( + "llm_chat", + authService.authentication.accessToken + ); + }); } - $scope.$apply(); } + ); + $scope.receiveMessage = function (msg) { + switch (msg.action) { + case "NewMessage": + $scope.newMessage(msg); + break; + } + }; + $scope.newMessage = function (msg) { + if ( + msg.data && + !angular.isObject(msg.data) && + msg.data.indexOf("{") == 0 + ) { + msg.data = JSON.parse(msg.data); + } + $scope.conversation.push({ + role: "ai", + content: msg.data.response, + }); + $scope.$apply(); }; }, ]); "use strict"; -app.factory("CustomerServices", [ - "$http", +app.factory("DashboardServices", [ "$rootScope", + "$http", "ApiService", "CommonService", - function ($http, $rootScope, apiService, commonService) { + function ($rootScope, $http, apiService, commonService) { //var serviceBase = 'http://ngauthenticationapi.azurewebsites.net/'; - var customersServiceFactory = {}; - - var settings = $rootScope.globalSettings; - - var _getCustomer = async function (id, type) { - var apiUrl = "/queen-beauty/customer/"; - var url = apiUrl + "details/" + type; - if (id) { - url += "/" + id; - } - var req = { - method: "GET", - url: url, - }; - return await apiService.sendRequest(req); - }; - - var _initCustomer = async function (type) { - var apiUrl = "/queen-beauty/customer/"; + var usersServiceFactory = {}; + var apiUrl = "/rest/portal/common/" + $rootScope.globalSettings.lang; + var _getDashboardInfo = async function () { var req = { method: "GET", - url: apiUrl + "init/" + type, - }; - return await apiService.sendRequest(req); - }; - - var _getCustomers = async function (request) { - var apiUrl = "/queen-beauty/customer/"; - var req = { - method: "POST", - url: apiUrl + "list", - data: JSON.stringify(request), + url: apiUrl + "/dashboard", }; - return await apiService.sendRequest(req); }; - var _removeCustomer = async function (id) { - var apiUrl = "/queen-beauty/customer/"; - var req = { - method: "GET", - url: apiUrl + "delete/" + id, - }; - return await apiService.sendRequest(req); - }; + usersServiceFactory.getDashboardInfo = _getDashboardInfo; + return usersServiceFactory; + }, +]); - var _saveCustomer = async function (customer) { - var apiUrl = "/queen-beauty/customer/"; - var req = { - method: "POST", - url: apiUrl + "save", - data: JSON.stringify(customer), - }; - return await apiService.sendRequest(req); - }; +"use strict"; +app.controller("DomainController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$location", + "$routeParams", + "DomainRestService", + function ( + $scope, + $rootScope, + ngAppSettings, + $location, + $routeParams, + service + ) { + BaseRestCtrl.call( + this, + $scope, + $rootScope, + $location, + $routeParams, + ngAppSettings, + service + ); + $scope.request.columns = [ + "id", + "displayName", + "host", + "createdDateTime", + "createdBy", + ]; + $scope.canDrag = + $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; + }, +]); - customersServiceFactory.getCustomer = _getCustomer; - customersServiceFactory.initCustomer = _initCustomer; - customersServiceFactory.getCustomers = _getCustomers; - customersServiceFactory.removeCustomer = _removeCustomer; - customersServiceFactory.saveCustomer = _saveCustomer; - return customersServiceFactory; +"use strict"; +app.factory("DomainRestService", [ + "BaseRestService", + function (baseService) { + var serviceFactory = Object.create(baseService); + serviceFactory.init("mix-domain"); + return serviceFactory; }, ]); "use strict"; -app.controller("JsonDataController", [ +app.controller("FileController", [ "$scope", "$rootScope", "ngAppSettings", @@ -1480,7 +1305,7 @@ app.controller("JsonDataController", [ "$timeout", "$location", "AuthService", - "JsonDataService", + "FileServices", function ( $scope, $rootScope, @@ -1489,13 +1314,13 @@ app.controller("JsonDataController", [ $timeout, $location, authService, - service + fileServices ) { $scope.request = { pageSize: "10", pageIndex: 0, status: "Published", - orderBy: "CreatedDateTime", + sortBy: "Id", direction: "Desc", fromDate: null, toDate: null, @@ -1504,35 +1329,39 @@ app.controller("JsonDataController", [ }; $scope.activedFile = null; - $scope.editorVisible = false; - $scope.data = null; $scope.relatedFiles = []; $rootScope.isBusy = false; - + $scope.data = { + pageIndex: 0, + pageSize: 1, + totalItems: 0, + }; $scope.errors = []; + $scope.range = function (max) { + var input = []; + for (var i = 1; i <= max; i += 1) input.push(i); + return input; + }; $scope.loadPage = async function (folder) { if (folder) { - $scope.request.key += $scope.request.key !== "" ? "/" : ""; - $scope.request.key += folder; + $scope.request.folder += $scope.request.folder !== "" ? "/" : ""; + $scope.request.folder += folder; } $location.url( - "/admin/json-data/list?folder=" + encodeURIComponent($scope.request.key) + "/admin/file/list?folder=" + encodeURIComponent($scope.request.folder) ); }; - $scope.init = async function () { + $scope.loadFile = async function () { $rootScope.isBusy = true; - $scope.filename = $routeParams.filename; - $scope.folder = $routeParams.folder; - $scope.listUrl = "/admin/json-data/list?folder=" + $routeParams.folder; + $scope.listUrl = "/admin/file/list?folder/" + $routeParams.folder; $rootScope.isBusy = true; - var response = await service.getFile( + var response = await fileServices.getFile( $routeParams.folder, $routeParams.filename ); if (response.success) { $scope.activedFile = response.data; - $scope.data = $.parseJSON(response.data.content); $rootScope.isBusy = false; $scope.$apply(); } else { @@ -1543,14 +1372,26 @@ app.controller("JsonDataController", [ }; $scope.loadFiles = async function (folder) { if (folder) { - $scope.request.key += $scope.request.key !== "" ? "/" : ""; - $scope.request.key += folder; - } else { - $scope.request.key = $routeParams.folder ? $routeParams.folder : "data"; + $scope.request.folder += + $scope.request.folder !== "" + ? "MixContent/StaticFiles" + : "MixContent/StaticFiles"; + $scope.request.folder += folder; + } else { + $scope.request.folder = $routeParams.folder + ? $routeParams.folder + : "MixContent/StaticFiles"; + } + if ($routeParams.folder) { + $scope.backUrl = + "/admin/file/list?folder=" + + $routeParams.folder.substring( + 0, + $routeParams.folder.lastIndexOf("/") + ); } - $rootScope.isBusy = true; - var resp = await service.getFiles($scope.request); + var resp = await fileServices.getFiles($scope.request); if (resp && resp.success) { $scope.data = resp.data; $.each($scope.data.items, function (i, file) { @@ -1574,7 +1415,7 @@ app.controller("JsonDataController", [ $scope.removeFile = async function (id) { if (confirm("Are you sure!")) { $rootScope.isBusy = true; - var resp = await service.removeFile(id); + var resp = await fileServices.removeFile(id); if (resp && resp.success) { $scope.loadFiles(); } else { @@ -1586,20 +1427,10 @@ app.controller("JsonDataController", [ } } }; - $scope.selectPane = function (pane) { - $scope.editorVisible = pane.header == "Content"; - }; - $scope.save = async function (data) { - $scope.activedFile.contennt = JSON.stringify(data); - $scope.saveFile($scope.activedFile); - }; - $scope.updateData = async function (data) { - $scope.data = data; - }; + $scope.saveFile = async function (file) { $rootScope.isBusy = true; - file.content = JSON.stringify($scope.data); - var resp = await service.saveFile(file); + var resp = await fileServices.saveFile(file); if (resp && resp.success) { $scope.activedFile = resp.data; $rootScope.showMessage("Update successfully!", "success"); @@ -1613,23 +1444,25 @@ app.controller("JsonDataController", [ $scope.$apply(); } }; + $scope.updateTemplateContent = function (content) { + $scope.activedFile.content = content; + }; }, ]); "use strict"; -app.factory("JsonDataService", [ +app.factory("FileServices", [ "$http", "$rootScope", "ApiService", "CommonService", - function ($http, $rootScope, apiService, commonService) { - var filesServiceFactory = {}; - - var settings = $rootScope.globalSettings; - + "BaseRestService", + function ($http, $rootScope, apiService, commonService, baseService) { + var filesServiceFactory = angular.copy(baseService); + filesServiceFactory.initService("/rest", "mix-storage/file-system", true); var _getFile = async function (folder, filename) { - var apiUrl = "/file/"; - var url = apiUrl + "details?folder=" + folder + "&filename=" + filename; + var url = + this.prefixUrl + "/details?folder=" + folder + "&filename=" + filename; var req = { method: "GET", url: url, @@ -1638,108 +1471,71 @@ app.factory("JsonDataService", [ }; var _initFile = async function (type) { - var apiUrl = "/file/"; var req = { method: "GET", - url: apiUrl + "init/" + type, + url: this.prefixUrl + "/init/" + type, }; return await apiService.sendRequest(req); }; var _getFiles = async function (request) { - var apiUrl = "/file/"; + var url = this.prefixUrl; + var data = filesServiceFactory.parseQuery(request); + if (data) { + url += "?"; + url = url.concat(data); + } var req = { - method: "POST", - url: apiUrl + "list", + method: "GET", + url: url, data: JSON.stringify(request), }; - return await apiService.sendRequest(req); }; - var _removeFile = async function (id) { - var apiUrl = "/file/"; + var _removeFile = async function (fullPath) { var req = { - method: "GET", - url: apiUrl + "delete/" + id, + method: "DELETE", + url: this.prefixUrl + "/delete/?fullPath=" + fullPath, }; return await apiService.sendRequest(req); }; var _saveFile = async function (file) { - var apiUrl = "/file/"; var req = { method: "POST", - url: apiUrl + "save", + url: this.prefixUrl + "/save", data: JSON.stringify(file), }; return await apiService.sendRequest(req); }; + var _uploadFile = async function (file, folder) { + var apiUrl = this.prefixUrl + "/upload-file"; + var fd = new FormData(); + fd.append("folder", folder); + fd.append("file", file); + return await filesServiceFactory.ajaxSubmitForm(fd, apiUrl); + }; + + var _extractFile = async function (file, folder) { + var apiUrl = this.prefixUrl + "/extract-file"; + var fd = new FormData(); + fd.append("folder", folder); + fd.append("file", file); + return await filesServiceFactory.ajaxSubmitForm(fd, apiUrl); + }; filesServiceFactory.getFile = _getFile; filesServiceFactory.initFile = _initFile; filesServiceFactory.getFiles = _getFiles; filesServiceFactory.removeFile = _removeFile; filesServiceFactory.saveFile = _saveFile; + filesServiceFactory.uploadFile = _uploadFile; + filesServiceFactory.extractFile = _extractFile; return filesServiceFactory; }, ]); -"use strict"; -app.controller("ImportFileController", [ - "$scope", - "$rootScope", - "ImportFileServices", - "TranslatorService", - "AppSettingsService", - function ( - $scope, - $rootScope, - service, - translatorService, - AppSettingsService - ) { - $scope.saveImportFile = async function () { - $rootScope.isBusy = true; - var form = document.getElementById("frm-import"); - var frm = new FormData(); - frm.append("assets", form["assets"].files[0]); - var response = await service.saveImportFile(frm); - if (response.success) { - $scope.viewmodel = response.data; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - }, -]); - -"use strict"; -app.factory("ImportFileServices", [ - "$rootScope", - "BaseService", - function ($rootScope, baseService) { - //var serviceBase = 'http://ngauthenticationapi.azurewebsites.net/'; - - var serviceFactory = {}; - - var settings = $rootScope.globalSettings; - var serviceFactory = Object.create(baseService); - serviceFactory.init("portal", true); - var _saveImportFile = async function (frm) { - var apiUrl = this.prefixUrl + "/" + settings.lang + "/import"; - return await this.ajaxSubmitForm(frm, apiUrl); - }; - - serviceFactory.saveImportFile = _saveImportFile; - return serviceFactory; - }, -]); - "use strict"; app.controller("GlobalSettingController", [ "$scope", @@ -1797,110 +1593,271 @@ app.factory("GlobalSettingService", [ ]); "use strict"; -app.controller("LocalizeController", [ +app.controller("ImportFileController", [ "$scope", "$rootScope", - "ngAppSettings", - "$routeParams", - "$location", - "LocalizeService", - "ApiService", + "ImportFileServices", + "TranslatorService", + "AppSettingsService", function ( $scope, $rootScope, - ngAppSettings, - $routeParams, - $location, service, - apiService + translatorService, + AppSettingsService ) { - BaseRestCtrl.call( - this, - $scope, - $rootScope, - $location, - $routeParams, - ngAppSettings, - service - ); - $scope.init = function () { - $scope.request.category = $routeParams.category || ""; - $scope.request.culture = $rootScope.globalSettings.defaultCulture; - $scope.getList(); - }; - $scope.getSingleSuccessCallback = function () { - $scope.cates = ngAppSettings.enums.configuration_cates; - $scope.appSettings = $rootScope.globalSettings; - $scope.request.category = $routeParams.category || ""; - if (!$scope.viewmodel.id) { - $scope.viewmodel.dataType = "Text"; - $scope.viewmodel.specificulture = - $rootScope.globalSettings.defaultCulture; - } - if (!$scope.viewmodel.category) { - $scope.viewmodel.category = "Site"; - } - }; - $scope.saveSuccessCallback = function () { - apiService.getAllSettings().then(function () { - // $location.url($scope.referrerUrl); + $scope.saveImportFile = async function () { + $rootScope.isBusy = true; + var form = document.getElementById("frm-import"); + var frm = new FormData(); + frm.append("assets", form["assets"].files[0]); + var response = await service.saveImportFile(frm); + if (response.success) { + $scope.viewmodel = response.data; $rootScope.isBusy = false; $scope.$apply(); - }); - }; - $scope.removeCallback = function () { - apiService.getAllSettings().then(function () { - $location.url($scope.referrerUrl); - }); - }; - - $scope.generateName = function () { - $scope.viewmodel.keyword = $rootScope.generateKeyword( - $scope.viewmodel.keyword, - "_", - true - ); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } }; }, ]); "use strict"; -app.factory("LocalizeService", [ - "BaseRestService", - "ApiService", - "CommonService", - function (baseService, apiService, commonService) { - var serviceFactory = Object.create(baseService); - serviceFactory.init("language"); - - var _uploadLanguage = async function (languageFile) { - //var container = $(this).parents('.model-language').first().find('.custom-file').first(); - if (languageFile.file !== undefined && languageFile.file !== null) { - // Create FormData object - var files = new FormData(); +app.factory("ImportFileServices", [ + "$rootScope", + "BaseService", + function ($rootScope, baseService) { + //var serviceBase = 'http://ngauthenticationapi.azurewebsites.net/'; - // Looping over all files and add it to FormData object - files.append(languageFile.file.name, languageFile.file); + var serviceFactory = {}; - // Adding one more key to FormData object - files.append("fileFolder", languageFile.folder); - files.append("title", languageFile.title); - files.append("description", languageFile.description); + var settings = $rootScope.globalSettings; + var serviceFactory = Object.create(baseService); + serviceFactory.init("portal", true); + var _saveImportFile = async function (frm) { + var apiUrl = this.prefixUrl + "/" + settings.lang + "/import"; + return await this.ajaxSubmitForm(frm, apiUrl); + }; - var req = { - url: this.prefixUrl + "/upload", - type: "POST", - headers: {}, - contentType: false, // Not to set any content header - processData: false, // Not to process data - data: files, - }; + serviceFactory.saveImportFile = _saveImportFile; + return serviceFactory; + }, +]); - return await apiService.sendRequest(req); +"use strict"; +app.controller("JsonDataController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$routeParams", + "$timeout", + "$location", + "AuthService", + "JsonDataService", + function ( + $scope, + $rootScope, + ngAppSettings, + $routeParams, + $timeout, + $location, + authService, + service + ) { + $scope.request = { + pageSize: "10", + pageIndex: 0, + status: "Published", + orderBy: "CreatedDateTime", + direction: "Desc", + fromDate: null, + toDate: null, + keyword: "", + key: "", + }; + + $scope.activedFile = null; + $scope.editorVisible = false; + $scope.data = null; + $scope.relatedFiles = []; + $rootScope.isBusy = false; + + $scope.errors = []; + + $scope.loadPage = async function (folder) { + if (folder) { + $scope.request.key += $scope.request.key !== "" ? "/" : ""; + $scope.request.key += folder; } + $location.url( + "/admin/json-data/list?folder=" + encodeURIComponent($scope.request.key) + ); }; - serviceFactory.uploadLanguage = _uploadLanguage; - return serviceFactory; + $scope.init = async function () { + $rootScope.isBusy = true; + $scope.filename = $routeParams.filename; + $scope.folder = $routeParams.folder; + $scope.listUrl = "/admin/json-data/list?folder=" + $routeParams.folder; + $rootScope.isBusy = true; + var response = await service.getFile( + $routeParams.folder, + $routeParams.filename + ); + if (response.success) { + $scope.activedFile = response.data; + $scope.data = $.parseJSON(response.data.content); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.loadFiles = async function (folder) { + if (folder) { + $scope.request.key += $scope.request.key !== "" ? "/" : ""; + $scope.request.key += folder; + } else { + $scope.request.key = $routeParams.folder ? $routeParams.folder : "data"; + } + + $rootScope.isBusy = true; + var resp = await service.getFiles($scope.request); + if (resp && resp.success) { + $scope.data = resp.data; + $.each($scope.data.items, function (i, file) { + $.each($scope.activedFiles, function (i, e) { + if (e.fileId === file.id) { + file.isHidden = true; + } + }); + }); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + + $scope.removeFile = async function (id) { + if (confirm("Are you sure!")) { + $rootScope.isBusy = true; + var resp = await service.removeFile(id); + if (resp && resp.success) { + $scope.loadFiles(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + } + }; + $scope.selectPane = function (pane) { + $scope.editorVisible = pane.header == "Content"; + }; + $scope.save = async function (data) { + $scope.activedFile.contennt = JSON.stringify(data); + $scope.saveFile($scope.activedFile); + }; + $scope.updateData = async function (data) { + $scope.data = data; + }; + $scope.saveFile = async function (file) { + $rootScope.isBusy = true; + file.content = JSON.stringify($scope.data); + var resp = await service.saveFile(file); + if (resp && resp.success) { + $scope.activedFile = resp.data; + $rootScope.showMessage("Update successfully!", "success"); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + }, +]); + +"use strict"; +app.factory("JsonDataService", [ + "$http", + "$rootScope", + "ApiService", + "CommonService", + function ($http, $rootScope, apiService, commonService) { + var filesServiceFactory = {}; + + var settings = $rootScope.globalSettings; + + var _getFile = async function (folder, filename) { + var apiUrl = "/file/"; + var url = apiUrl + "details?folder=" + folder + "&filename=" + filename; + var req = { + method: "GET", + url: url, + }; + return await apiService.sendRequest(req); + }; + + var _initFile = async function (type) { + var apiUrl = "/file/"; + var req = { + method: "GET", + url: apiUrl + "init/" + type, + }; + return await apiService.sendRequest(req); + }; + + var _getFiles = async function (request) { + var apiUrl = "/file/"; + var req = { + method: "POST", + url: apiUrl + "list", + data: JSON.stringify(request), + }; + + return await apiService.sendRequest(req); + }; + + var _removeFile = async function (id) { + var apiUrl = "/file/"; + var req = { + method: "GET", + url: apiUrl + "delete/" + id, + }; + return await apiService.sendRequest(req); + }; + + var _saveFile = async function (file) { + var apiUrl = "/file/"; + var req = { + method: "POST", + url: apiUrl + "save", + data: JSON.stringify(file), + }; + return await apiService.sendRequest(req); + }; + + filesServiceFactory.getFile = _getFile; + filesServiceFactory.initFile = _initFile; + filesServiceFactory.getFiles = _getFiles; + filesServiceFactory.removeFile = _removeFile; + filesServiceFactory.saveFile = _saveFile; + return filesServiceFactory; }, ]); @@ -2017,22 +1974,22 @@ app.controller("loginController", [ ]); "use strict"; -app.controller("MixDbDataController", [ +app.controller("LocalizeController", [ "$scope", "$rootScope", "ngAppSettings", "$routeParams", "$location", - "RestMixDbTablePortalService", - "MixDbDataService", + "LocalizeService", + "ApiService", function ( $scope, $rootScope, ngAppSettings, $routeParams, $location, - databaseService, - mixDbService + service, + apiService ) { BaseRestCtrl.call( this, @@ -2041,28 +1998,136 @@ app.controller("MixDbDataController", [ $location, $routeParams, ngAppSettings, - mixDbService + service ); - $scope.queries = {}; - $scope.data = null; - $scope.exportAll = true; - $scope.mixConfigurations = $rootScope.globalSettings; - $scope.filterType = "contain"; - $scope.dataContentId = null; - $scope.hiddenColumns = [ - "created_date_time", - "last_modified", - "tenant_id", - "created_by", - "modified_by", - "priority", - "status", - "is_deleted", - ]; - $scope.importFile = { - file: null, - fullPath: "", - folder: "import", + $scope.init = function () { + $scope.request.category = $routeParams.category || ""; + $scope.request.culture = $rootScope.globalSettings.defaultCulture; + $scope.getList(); + }; + $scope.getSingleSuccessCallback = function () { + $scope.cates = ngAppSettings.enums.configuration_cates; + $scope.appSettings = $rootScope.globalSettings; + $scope.request.category = $routeParams.category || ""; + if (!$scope.viewmodel.id) { + $scope.viewmodel.dataType = "Text"; + $scope.viewmodel.specificulture = + $rootScope.globalSettings.defaultCulture; + } + if (!$scope.viewmodel.category) { + $scope.viewmodel.category = "Site"; + } + }; + $scope.saveSuccessCallback = function () { + apiService.getAllSettings().then(function () { + // $location.url($scope.referrerUrl); + $rootScope.isBusy = false; + $scope.$apply(); + }); + }; + $scope.removeCallback = function () { + apiService.getAllSettings().then(function () { + $location.url($scope.referrerUrl); + }); + }; + + $scope.generateName = function () { + $scope.viewmodel.keyword = $rootScope.generateKeyword( + $scope.viewmodel.keyword, + "_", + true + ); + }; + }, +]); + +"use strict"; +app.factory("LocalizeService", [ + "BaseRestService", + "ApiService", + "CommonService", + function (baseService, apiService, commonService) { + var serviceFactory = Object.create(baseService); + serviceFactory.init("language"); + + var _uploadLanguage = async function (languageFile) { + //var container = $(this).parents('.model-language').first().find('.custom-file').first(); + if (languageFile.file !== undefined && languageFile.file !== null) { + // Create FormData object + var files = new FormData(); + + // Looping over all files and add it to FormData object + files.append(languageFile.file.name, languageFile.file); + + // Adding one more key to FormData object + files.append("fileFolder", languageFile.folder); + files.append("title", languageFile.title); + files.append("description", languageFile.description); + + var req = { + url: this.prefixUrl + "/upload", + type: "POST", + headers: {}, + contentType: false, // Not to set any content header + processData: false, // Not to process data + data: files, + }; + + return await apiService.sendRequest(req); + } + }; + serviceFactory.uploadLanguage = _uploadLanguage; + return serviceFactory; + }, +]); + +"use strict"; +app.controller("MixDbDataController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$routeParams", + "$location", + "RestMixDbTablePortalService", + "MixDbDataService", + function ( + $scope, + $rootScope, + ngAppSettings, + $routeParams, + $location, + databaseService, + mixDbService + ) { + BaseRestCtrl.call( + this, + $scope, + $rootScope, + $location, + $routeParams, + ngAppSettings, + mixDbService + ); + $scope.queries = {}; + $scope.data = null; + $scope.exportAll = true; + $scope.mixConfigurations = $rootScope.globalSettings; + $scope.filterType = "contain"; + $scope.dataContentId = null; + $scope.hiddenColumns = [ + "created_date_time", + "last_modified", + "tenant_id", + "created_by", + "modified_by", + "priority", + "status", + "is_deleted", + ]; + $scope.importFile = { + file: null, + fullPath: "", + folder: "import", title: "", description: "", }; @@ -2410,12 +2475,15 @@ app.controller("MixDbDataController", [ ]); "use strict"; -app.controller("MixDbDatabaseController", [ +app.controller("MixDbTableController", [ "$scope", "$rootScope", "$location", "ngAppSettings", "$routeParams", + "RestMixDbDataPortalService", + "RestMixDbColumnPortalService", + "RestMixDbTablePortalService", "RestMixDbDatabaseService", function ( $scope, @@ -2423,7 +2491,10 @@ app.controller("MixDbDatabaseController", [ $location, ngAppSettings, $routeParams, - mixdbContextService + mixDbDataService, + mixDbColumnService, + mixDbTableService, + mixDbDatabaseService ) { BaseRestCtrl.call( this, @@ -2432,104 +2503,145 @@ app.controller("MixDbDatabaseController", [ $location, $routeParams, ngAppSettings, - mixdbContextService + mixDbTableService ); - $scope.namingConventions = ["SnakeCase"]; $scope.defaultAttr = null; - $scope.databaseProvider = [ - "MySQL", - "PostgreSQL", - "SQLITE", - "SQLSERVER", - "SCYLLADB", - ]; $scope.actions = ["Delete"]; + $scope.viewmodelType = "mix-db-table"; // $scope.request.selects = 'id,title,name,createdDateTime'; $scope.orders = [ { title: "Id", value: "Id" }, - { title: "Name", value: "DisplayName" }, + { title: "Name", value: "Name" }, { title: "Created Date", value: "CreatedDateTime" }, ]; $scope.request.sortBy = "id"; $scope.request.columns = "id,displayName,systemName,type,createdDatetime"; $scope.request.searchColumns = "displayName,systemName"; + $scope.initList = async function () { + $scope.request.mixDbDatabaseId = $routeParams.mixDbDatabaseId; + await $scope.getList(); + }; $scope.saveDatabase = function () { $scope.save($scope.viewmodel); }; - $scope.migrate = async function () { - $rootScope.isBusy = true; - var resp = await mixdbContextService.migrate($scope.viewmodel); - if (resp.success) { - $rootScope.showMessage("success", "success"); - } else if (resp) { - $rootScope.showErrors(resp.errors); + + $scope.getSingleSuccessCallback = async function () { + if (!$scope.viewmodel.mixDbDatabaseId) { + $scope.viewmodel.mixDbDatabaseId = $routeParams.mixDbDatabaseId; + } + $scope.viewmodel.namingConvention = + $routeParams.namingConvention || "TitleCase"; + if ($scope.viewmodel.mixDbDatabaseId) { + var resp = await mixDbDatabaseService.getSingle([ + $scope.viewmodel.mixDbDatabaseId, + ]); + if (resp.success) { + $scope.dbContext = resp.data; + } + } + if (!$scope.defaultAttr) { + var getDefaultAttr = await mixDbColumnService.getDefault(); + if (getDefaultAttr.success) { + $scope.defaultAttr = getDefaultAttr.data; + $scope.defaultAttr.options = []; + } + $scope.$apply(); } - $rootScope.isBusy = false; - $scope.$apply(); - }; - $scope.generateName = function () { - $scope.viewmodel.systemName = $rootScope.generateKeyword( - $scope.viewmodel.displayName, - "_", - true, - true - ); }; - $scope.getSingleSuccessCallback = async function () {}; - }, -]); - -"use strict"; -app.factory("RestMixDbDatabaseService", [ - "BaseRestService", - function (baseService) { - var serviceFactory = Object.create(baseService); - serviceFactory.init("mix-db-database"); - - var _getByName = async function (name) { - var url = `${this.prefixUrl}/get-by-name/${name}`; - var req = { - method: "GET", - url: url, - }; - return await this.getRestApiResult(req); + $scope.migrate = async function () { + if ($scope.viewmodel.id) { + $rootScope.isBusy = true; + var result = await mixDbTableService.migrate($scope.viewmodel); + if (result.success) { + $rootScope.showMessage( + "Please restart pool to apply new db schema", + "warning" + ); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(["Cannot migrate database"]); + $rootScope.isBusy = false; + $scope.$apply(); + } + } }; - var _migrate = async function (dbContext) { - var url = `${this.prefixUrl}/migrate`; - var req = { - method: "POST", - url: url, - data: dbContext, - }; - return await this.getRestApiResult(req); + $scope.backup = async function () { + if ($scope.viewmodel.id) { + $rootScope.isBusy = true; + var result = await mixDbTableService.backup($scope.viewmodel); + if (result.success) { + $rootScope.showMessage( + `Backup ${$scope.viewmodel.systemName} is queued`, + "success" + ); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(["Cannot backup database"]); + $rootScope.isBusy = false; + $scope.$apply(); + } + } + }; + $scope.restore = async function () { + if ($scope.viewmodel.id) { + $rootScope.isBusy = true; + var result = await mixDbTableService.restore($scope.viewmodel); + if (result.success) { + $rootScope.showMessage( + `Restore ${$scope.viewmodel.systemName} is queued`, + "success" + ); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(["Cannot restore database"]); + $rootScope.isBusy = false; + $scope.$apply(); + } + } + }; + $scope.updateSchema = async function () { + if ($scope.viewmodel.id) { + $rootScope.isBusy = true; + var result = await mixDbTableService.updateSchema($scope.viewmodel); + if (result.success) { + $rootScope.showMessage( + "Please restart pool to apply new db schema", + "warning" + ); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(["Cannot update database"]); + $rootScope.isBusy = false; + $scope.$apply(); + } + } + }; + + $scope.back = function () { + window.history.back(); }; - serviceFactory.getByName = _getByName; - serviceFactory.migrate = _migrate; - return serviceFactory; }, ]); "use strict"; -app.controller("ModuleController", [ +app.controller("MixDbDatabaseController", [ "$scope", "$rootScope", - "ngAppSettings", "$location", + "ngAppSettings", "$routeParams", - "ModuleRestService", - "SharedModuleDataService", - "RestMixDbDataPortalService", - "RestMixDbColumnPortalService", + "RestMixDbDatabaseService", function ( $scope, $rootScope, - ngAppSettings, $location, + ngAppSettings, $routeParams, - moduleServices, - moduleDataService, - dataService, - columnService + mixdbContextService ) { BaseRestCtrl.call( this, @@ -2538,83 +2650,130 @@ app.controller("ModuleController", [ $location, $routeParams, ngAppSettings, - moduleServices, - "product" + mixdbContextService ); - $scope.request.culture = $rootScope.globalSettings.defaultCulture; - $scope.viewmodelType = "module"; - $scope.contentUrl = ""; - $scope.getSingleSuccessCallback = function () { - $scope.loadAdditionalData(); - - if ($scope.viewmodel.id > 0) { - // module => list post or list product - if ($scope.viewmodel.type.localeCompare("ListPost") == 0) { - $scope.contentUrl = "/admin/module-post/list/" + $scope.viewmodel.id; - } else if ($scope.viewmodel.type.localeCompare("Data") == 0) { - $scope.contentUrl = "/admin/module-data/list/" + $scope.viewmodel.id; - } - } - if ($scope.viewmodel.sysCategories) { - angular.forEach($scope.viewmodel.sysCategories, function (e) { - e.attributeData.obj.isActived = true; - }); + $scope.namingConventions = ["SnakeCase"]; + $scope.defaultAttr = null; + $scope.databaseProvider = [ + "MySQL", + "PostgreSQL", + "SQLITE", + "SQLSERVER", + "SCYLLADB", + ]; + $scope.actions = ["Delete"]; + // $scope.request.selects = 'id,title,name,createdDateTime'; + $scope.orders = [ + { title: "Id", value: "Id" }, + { title: "Name", value: "DisplayName" }, + { title: "Created Date", value: "CreatedDateTime" }, + ]; + $scope.request.sortBy = "id"; + $scope.request.columns = "id,displayName,systemName,type,createdDatetime"; + $scope.request.searchColumns = "displayName,systemName"; + $scope.saveDatabase = function () { + $scope.save($scope.viewmodel); + }; + $scope.migrate = async function () { + $rootScope.isBusy = true; + var resp = await mixdbContextService.migrate($scope.viewmodel); + if (resp.success) { + $rootScope.showMessage("success", "success"); + } else if (resp) { + $rootScope.showErrors(resp.errors); } + $rootScope.isBusy = false; + $scope.$apply(); + }; + $scope.generateName = function () { + $scope.viewmodel.systemName = $rootScope.generateKeyword( + $scope.viewmodel.displayName, + "_", + true, + true + ); + }; + $scope.getSingleSuccessCallback = async function () {}; + }, +]); - if ($scope.viewmodel.sysTags) { - angular.forEach($scope.viewmodel.sysTags, function (e) { - e.attributeData.obj.isActived = true; - }); - } +"use strict"; +app.factory("RestMixDbDatabaseService", [ + "BaseRestService", + function (baseService) { + var serviceFactory = Object.create(baseService); + serviceFactory.init("mix-db-database"); - if ($routeParams.template) { - $scope.viewmodel.view = $rootScope.findObjectByKey( - $scope.viewmodel.templates, - "fileName", - $routeParams.template - ); - } - }; - $scope.getListByType = async function (pageIndex) { - $scope.request.query = "?type=" + $scope.type; - await $scope.getList(pageIndex); + var _getByName = async function (name) { + var url = `${this.prefixUrl}/get-by-name/${name}`; + var req = { + method: "GET", + url: url, + }; + return await this.getRestApiResult(req); }; - $scope.defaultAttr = { - name: "", - options: [], - priority: 0, - dataType: 7, - isGroupBy: false, - isSelect: false, - isDisplay: true, - width: 3, + var _migrate = async function (dbContext) { + var url = `${this.prefixUrl}/migrate`; + var req = { + method: "POST", + url: url, + data: dbContext, + }; + return await this.getRestApiResult(req); }; - $scope.type = "-1"; - - $scope.localizeSettings = $rootScope.globalSettings; - $scope.viewmodel = null; - $scope.editDataUrl = ""; + serviceFactory.getByName = _getByName; + serviceFactory.migrate = _migrate; + return serviceFactory; + }, +]); - $scope.loadModuleDatas = async function () { +"use strict"; +app.controller("ModuleGalleryController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$routeParams", + "$location", + "ModuleGalleryService", + "ApiService", + "CommonService", + function ( + $scope, + $rootScope, + ngAppSettings, + $routeParams, + $location, + service, + apiService, + commonService + ) { + BaseCtrl.call( + this, + $scope, + $rootScope, + $routeParams, + ngAppSettings, + service + ); + $scope.cates = ["Site", "System"]; + $scope.others = []; + $scope.mixConfigurations = $rootScope.globalSettings; + $scope.moduleContentId = $routeParams.id; + $scope.canDrag = + $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; + $scope.translate = $rootScope.translate; + $scope.moduleContentId = $routeParams.id; + $scope.getList = async function () { $rootScope.isBusy = true; var id = $routeParams.id; - $scope.dataColumns = []; - var response = await moduleServices.getSingle([id]); + $scope.moduleContentId = $routeParams.id; + $scope.request.query = "&moduleContentId=" + id; + $scope.canDrag = + $scope.request.sortBy !== "Priority" || + $scope.request.direction !== "0"; + var response = await service.getList($scope.request); if (response.success) { - $scope.viewmodel = response.data; - $scope.editDataUrl = - "/admin/module-data/details/" + $scope.viewmodel.id; - $scope.loadMoreModuleDatas(); - angular.forEach($scope.viewmodel.columns, function (e, i) { - if (e.isDisplay) { - $scope.dataColumns.push({ - title: e.title, - name: e.name, - filter: true, - type: 0, // string - ngAppSettings.dataTypes[0] - }); - } - }); + $scope.data = response.data; $rootScope.isBusy = false; $scope.$apply(); } else { @@ -2623,15 +2782,227 @@ app.controller("ModuleController", [ $scope.$apply(); } }; + $scope.remove = function (moduleContentId, postId) { + $rootScope.showConfirm( + $scope, + "removeConfirmed", + [moduleContentId, postId], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; - $scope.loadMoreModuleDatas = async function (pageIndex) { - $scope.request.query = "&moduleContentId=" + $scope.viewmodel.id; - if (pageIndex !== undefined) { - $scope.request.pageIndex = pageIndex; - } - if ($scope.request.fromDate !== null) { - var d = new Date($scope.request.fromDate); - $scope.request.fromDate = d.toISOString(); + $scope.removeConfirmed = async function (moduleContentId, postId) { + $rootScope.isBusy = true; + var result = await service.delete(moduleContentId, postId); + if (result.success) { + if ($scope.removeCallback) { + $rootScope.executeFunctionByName( + "removeCallback", + $scope.removeCallbackArgs, + $scope + ); + } + $scope.getList(); + } else { + $rootScope.showMessage("failed"); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + + $scope.removeCallback = function () {}; + + $scope.saveOthers = async function () { + var response = await service.saveList($scope.others); + if (response.success) { + $scope.getList(); + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.updateInfos = async function (index) { + $scope.data.items.splice(index, 1); + $rootScope.isBusy = true; + var startIndex = $scope.data.items[0].priority - 1; + for (var i = 0; i < $scope.data.items.length; i++) { + $scope.data.items[i].priority = startIndex + i + 1; + } + var resp = await service.updateInfos($scope.data.items); + if (resp && resp.success) { + $scope.activedPage = resp.data; + $rootScope.showMessage("success", "success"); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + }, +]); + +"use strict"; +app.factory("ModuleGalleryService", [ + "$rootScope", + "ApiService", + "CommonService", + "BaseService", + function ($rootScope, apiService, commonService, baseService) { + var serviceFactory = Object.create(baseService); + serviceFactory.init("module-post"); + var _delete = async function (moduleContentId, postId) { + var url = this.prefixUrl + "/delete/" + moduleContentId + "/" + postId; + var req = { + method: "GET", + url: url, + }; + return await apiService.sendRequest(req); + }; + var _updateInfos = async function (modules) { + var req = { + method: "POST", + url: this.prefixUrl + "/update-infos", + data: JSON.stringify(modules), + }; + return await apiService.sendRequest(req); + }; + serviceFactory.delete = _delete; + serviceFactory.updateInfos = _updateInfos; + return serviceFactory; + }, +]); + +"use strict"; +app.controller("ModuleController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$location", + "$routeParams", + "ModuleRestService", + "SharedModuleDataService", + "RestMixDbDataPortalService", + "RestMixDbColumnPortalService", + function ( + $scope, + $rootScope, + ngAppSettings, + $location, + $routeParams, + moduleServices, + moduleDataService, + dataService, + columnService + ) { + BaseRestCtrl.call( + this, + $scope, + $rootScope, + $location, + $routeParams, + ngAppSettings, + moduleServices, + "product" + ); + $scope.request.culture = $rootScope.globalSettings.defaultCulture; + $scope.viewmodelType = "module"; + $scope.contentUrl = ""; + $scope.getSingleSuccessCallback = function () { + $scope.loadAdditionalData(); + + if ($scope.viewmodel.id > 0) { + // module => list post or list product + if ($scope.viewmodel.type.localeCompare("ListPost") == 0) { + $scope.contentUrl = "/admin/module-post/list/" + $scope.viewmodel.id; + } else if ($scope.viewmodel.type.localeCompare("Data") == 0) { + $scope.contentUrl = "/admin/module-data/list/" + $scope.viewmodel.id; + } + } + if ($scope.viewmodel.sysCategories) { + angular.forEach($scope.viewmodel.sysCategories, function (e) { + e.attributeData.obj.isActived = true; + }); + } + + if ($scope.viewmodel.sysTags) { + angular.forEach($scope.viewmodel.sysTags, function (e) { + e.attributeData.obj.isActived = true; + }); + } + + if ($routeParams.template) { + $scope.viewmodel.view = $rootScope.findObjectByKey( + $scope.viewmodel.templates, + "fileName", + $routeParams.template + ); + } + }; + $scope.getListByType = async function (pageIndex) { + $scope.request.query = "?type=" + $scope.type; + await $scope.getList(pageIndex); + }; + $scope.defaultAttr = { + name: "", + options: [], + priority: 0, + dataType: 7, + isGroupBy: false, + isSelect: false, + isDisplay: true, + width: 3, + }; + $scope.type = "-1"; + + $scope.localizeSettings = $rootScope.globalSettings; + $scope.viewmodel = null; + $scope.editDataUrl = ""; + + $scope.loadModuleDatas = async function () { + $rootScope.isBusy = true; + var id = $routeParams.id; + $scope.dataColumns = []; + var response = await moduleServices.getSingle([id]); + if (response.success) { + $scope.viewmodel = response.data; + $scope.editDataUrl = + "/admin/module-data/details/" + $scope.viewmodel.id; + $scope.loadMoreModuleDatas(); + angular.forEach($scope.viewmodel.columns, function (e, i) { + if (e.isDisplay) { + $scope.dataColumns.push({ + title: e.title, + name: e.name, + filter: true, + type: 0, // string - ngAppSettings.dataTypes[0] + }); + } + }); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + + $scope.loadMoreModuleDatas = async function (pageIndex) { + $scope.request.query = "&moduleContentId=" + $scope.viewmodel.id; + if (pageIndex !== undefined) { + $scope.request.pageIndex = pageIndex; + } + if ($scope.request.fromDate !== null) { + var d = new Date($scope.request.fromDate); + $scope.request.fromDate = d.toISOString(); } if ($scope.request.toDate !== null) { var d = new Date($scope.request.toDate); @@ -2988,203 +3359,60 @@ app.factory("ModuleDataRestService", [ ]); "use strict"; -app.controller("MixDbTableController", [ +app.controller("ModulePostController", [ "$scope", "$rootScope", - "$location", "ngAppSettings", "$routeParams", - "RestMixDbDataPortalService", - "RestMixDbColumnPortalService", - "RestMixDbTablePortalService", - "RestMixDbDatabaseService", + "$location", + "ModulePostRestService", + "ApiService", + "CommonService", function ( $scope, $rootScope, - $location, ngAppSettings, $routeParams, - mixDbDataService, - mixDbColumnService, - mixDbTableService, - mixDbDatabaseService + $location, + service, + commonService ) { - BaseRestCtrl.call( + BaseCtrl.call( this, $scope, $rootScope, - $location, $routeParams, ngAppSettings, - mixDbTableService - ); - $scope.defaultAttr = null; - $scope.actions = ["Delete"]; - $scope.viewmodelType = "mix-db-table"; - // $scope.request.selects = 'id,title,name,createdDateTime'; - $scope.orders = [ - { title: "Id", value: "Id" }, - { title: "Name", value: "Name" }, - { title: "Created Date", value: "CreatedDateTime" }, - ]; - $scope.request.sortBy = "id"; - $scope.request.columns = "id,displayName,systemName,type,createdDatetime"; - $scope.request.searchColumns = "displayName,systemName"; - $scope.initList = async function () { - $scope.request.mixDbDatabaseId = $routeParams.mixDbDatabaseId; - await $scope.getList(); - }; - $scope.saveDatabase = function () { - $scope.save($scope.viewmodel); - }; - - $scope.getSingleSuccessCallback = async function () { - if (!$scope.viewmodel.mixDbDatabaseId) { - $scope.viewmodel.mixDbDatabaseId = $routeParams.mixDbDatabaseId; - } - $scope.viewmodel.namingConvention = - $routeParams.namingConvention || "TitleCase"; - if ($scope.viewmodel.mixDbDatabaseId) { - var resp = await mixDbDatabaseService.getSingle([ - $scope.viewmodel.mixDbDatabaseId, - ]); - if (resp.success) { - $scope.dbContext = resp.data; - } - } - if (!$scope.defaultAttr) { - var getDefaultAttr = await mixDbColumnService.getDefault(); - if (getDefaultAttr.success) { - $scope.defaultAttr = getDefaultAttr.data; - $scope.defaultAttr.options = []; - } - $scope.$apply(); - } - }; - $scope.migrate = async function () { - if ($scope.viewmodel.id) { - $rootScope.isBusy = true; - var result = await mixDbTableService.migrate($scope.viewmodel); - if (result.success) { - $rootScope.showMessage( - "Please restart pool to apply new db schema", - "warning" - ); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(["Cannot migrate database"]); - $rootScope.isBusy = false; - $scope.$apply(); - } - } - }; - $scope.backup = async function () { - if ($scope.viewmodel.id) { - $rootScope.isBusy = true; - var result = await mixDbTableService.backup($scope.viewmodel); - if (result.success) { - $rootScope.showMessage( - `Backup ${$scope.viewmodel.systemName} is queued`, - "success" - ); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(["Cannot backup database"]); - $rootScope.isBusy = false; - $scope.$apply(); - } - } - }; - $scope.restore = async function () { - if ($scope.viewmodel.id) { - $rootScope.isBusy = true; - var result = await mixDbTableService.restore($scope.viewmodel); - if (result.success) { - $rootScope.showMessage( - `Restore ${$scope.viewmodel.systemName} is queued`, - "success" - ); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(["Cannot restore database"]); - $rootScope.isBusy = false; - $scope.$apply(); - } - } - }; - $scope.updateSchema = async function () { - if ($scope.viewmodel.id) { - $rootScope.isBusy = true; - var result = await mixDbTableService.updateSchema($scope.viewmodel); - if (result.success) { - $rootScope.showMessage( - "Please restart pool to apply new db schema", - "warning" - ); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(["Cannot update database"]); - $rootScope.isBusy = false; - $scope.$apply(); - } - } - }; - - $scope.back = function () { - window.history.back(); - }; - }, -]); - -"use strict"; -app.controller("ModuleGalleryController", [ - "$scope", - "$rootScope", - "ngAppSettings", - "$routeParams", - "$location", - "ModuleGalleryService", - "ApiService", - "CommonService", - function ( - $scope, - $rootScope, - ngAppSettings, - $routeParams, - $location, - service, - apiService, - commonService - ) { - BaseCtrl.call( - this, - $scope, - $rootScope, - $routeParams, - ngAppSettings, - service + service ); + $scope.request.culture = $rootScope.globalSettings.defaultCulture; $scope.cates = ["Site", "System"]; $scope.others = []; $scope.mixConfigurations = $rootScope.globalSettings; - $scope.moduleContentId = $routeParams.id; $scope.canDrag = $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; $scope.translate = $rootScope.translate; - $scope.moduleContentId = $routeParams.id; - $scope.getList = async function () { + $scope.moduleIds = $routeParams.moduleIds || $routeParams.id; + $scope.pageIds = $routeParams.page_ids; + $scope.type = $routeParams.type; + $scope.template = $routeParams.template || ""; + + $scope.init = function () { + $scope.createUrl = `/admin/post/create?page_ids=${$scope.pageIds}&moduleIds=${$scope.moduleIds}&type=${$scope.type}&template=${$scope.template}`; + $scope.getList(); + }; + $scope.getList = async function (pageIndex) { $rootScope.isBusy = true; + if (pageIndex !== undefined) { + $scope.request.pageIndex = pageIndex; + } var id = $routeParams.id; $scope.moduleContentId = $routeParams.id; - $scope.request.query = "&moduleContentId=" + id; + $scope.request.parentId = id; $scope.canDrag = $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; - var response = await service.getList($scope.request); + var response = await service.search($scope.request); if (response.success) { $scope.data = response.data; $rootScope.isBusy = false; @@ -3195,20 +3423,24 @@ app.controller("ModuleGalleryController", [ $scope.$apply(); } }; - $scope.remove = function (moduleContentId, postId) { + $scope.preview = function (item) { + item.editUrl = "/admin/post/details/" + item.id; + $rootScope.preview("post", item, item.title, "modal-lg"); + }; + $scope.remove = function (id) { $rootScope.showConfirm( $scope, "removeConfirmed", - [moduleContentId, postId], + [id], null, "Remove", "Deleted data will not able to recover, are you sure you want to delete this item?" ); }; - $scope.removeConfirmed = async function (moduleContentId, postId) { + $scope.removeConfirmed = async function (id) { $rootScope.isBusy = true; - var result = await service.delete(moduleContentId, postId); + var result = await service.delete(id); if (result.success) { if ($scope.removeCallback) { $rootScope.executeFunctionByName( @@ -3263,20 +3495,37 @@ app.controller("ModuleGalleryController", [ ]); "use strict"; -app.factory("ModuleGalleryService", [ +app.factory("ModulePostRestService", [ "$rootScope", "ApiService", "CommonService", - "BaseService", + "BaseRestService", function ($rootScope, apiService, commonService, baseService) { var serviceFactory = Object.create(baseService); serviceFactory.init("module-post"); - var _delete = async function (moduleContentId, postId) { - var url = this.prefixUrl + "/delete/" + moduleContentId + "/" + postId; + + var _search = async function (objData) { + var data = serviceFactory.parseQuery(objData); + var url = this.prefixUrl; + + if (data) { + url += "/search?"; + url = url.concat(data); + } var req = { + serviceBase: this.serviceBase, method: "GET", url: url, }; + return await this.getRestApiResult(req); + }; + + var _delete = async function (id) { + var url = this.prefixUrl + "/" + id; + var req = { + method: "DELETE", + url: url, + }; return await apiService.sendRequest(req); }; var _updateInfos = async function (modules) { @@ -3287,6 +3536,7 @@ app.factory("ModuleGalleryService", [ }; return await apiService.sendRequest(req); }; + serviceFactory.search = _search; serviceFactory.delete = _delete; serviceFactory.updateInfos = _updateInfos; return serviceFactory; @@ -3294,259 +3544,74 @@ app.factory("ModuleGalleryService", [ ]); "use strict"; -app.controller("ModulePostController", [ +app.controller("PageController", [ "$scope", "$rootScope", "ngAppSettings", - "$routeParams", "$location", - "ModulePostRestService", - "ApiService", - "CommonService", + "$routeParams", + "PageRestService", + "PagePostRestService", + "UrlAliasService", + "RestMixDbTablePortalService", + "RestMixDbDataPortalService", + "RestMixDbColumnPortalService", + "MixDbDataService", function ( $scope, $rootScope, ngAppSettings, - $routeParams, $location, + $routeParams, service, - commonService + pagePostRestService, + urlAliasService, + databaseService, + dataService, + columnService, + mixDbService ) { - BaseCtrl.call( + BaseRestCtrl.call( this, $scope, $rootScope, + $location, $routeParams, ngAppSettings, service ); $scope.request.culture = $rootScope.globalSettings.defaultCulture; - $scope.cates = ["Site", "System"]; - $scope.others = []; - $scope.mixConfigurations = $rootScope.globalSettings; + var pageModuleService = $rootScope.getRestService("page-module"); + $scope.viewmodelType = "page"; + $scope.request.query = "level=0"; + $scope.pageType = {}; + $scope.pageTypes = $rootScope.globalSettings.pageTypes; + $scope.selectedCategories = []; + $scope.selectedTags = []; + $scope.selectedModules = []; + $scope.pageData = { + posts: [], + products: [], + data: [], + }; + $scope.request.columns = [ + "id", + "title", + "createdDateTime", + "type", + "image", + "detailUrl", + ]; + $scope.additionalData = null; + $scope.temp = null; + $scope.postRequest = angular.copy(ngAppSettings.request); + $scope.additionalDatabaseRequest = angular.copy(ngAppSettings.request); + ($scope.additionalDatabaseRequest.searchColumns = "Type"), + ($scope.additionalDatabaseRequest.compareOperator = "Equal"), + ($scope.additionalDatabaseRequest.keyword = "AdditionalData"); $scope.canDrag = $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; - $scope.translate = $rootScope.translate; - $scope.moduleIds = $routeParams.moduleIds || $routeParams.id; - $scope.pageIds = $routeParams.page_ids; - $scope.type = $routeParams.type; - $scope.template = $routeParams.template || ""; - - $scope.init = function () { - $scope.createUrl = `/admin/post/create?page_ids=${$scope.pageIds}&moduleIds=${$scope.moduleIds}&type=${$scope.type}&template=${$scope.template}`; - $scope.getList(); - }; - $scope.getList = async function (pageIndex) { - $rootScope.isBusy = true; - if (pageIndex !== undefined) { - $scope.request.pageIndex = pageIndex; - } - var id = $routeParams.id; - $scope.moduleContentId = $routeParams.id; - $scope.request.parentId = id; - $scope.canDrag = - $scope.request.sortBy !== "Priority" || - $scope.request.direction !== "0"; - var response = await service.search($scope.request); - if (response.success) { - $scope.data = response.data; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.preview = function (item) { - item.editUrl = "/admin/post/details/" + item.id; - $rootScope.preview("post", item, item.title, "modal-lg"); - }; - $scope.remove = function (id) { - $rootScope.showConfirm( - $scope, - "removeConfirmed", - [id], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); - }; - - $scope.removeConfirmed = async function (id) { - $rootScope.isBusy = true; - var result = await service.delete(id); - if (result.success) { - if ($scope.removeCallback) { - $rootScope.executeFunctionByName( - "removeCallback", - $scope.removeCallbackArgs, - $scope - ); - } - $scope.getList(); - } else { - $rootScope.showMessage("failed"); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - - $scope.removeCallback = function () {}; - - $scope.saveOthers = async function () { - var response = await service.saveList($scope.others); - if (response.success) { - $scope.getList(); - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.updateInfos = async function (index) { - $scope.data.items.splice(index, 1); - $rootScope.isBusy = true; - var startIndex = $scope.data.items[0].priority - 1; - for (var i = 0; i < $scope.data.items.length; i++) { - $scope.data.items[i].priority = startIndex + i + 1; - } - var resp = await service.updateInfos($scope.data.items); - if (resp && resp.success) { - $scope.activedPage = resp.data; - $rootScope.showMessage("success", "success"); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - }, -]); - -"use strict"; -app.factory("ModulePostRestService", [ - "$rootScope", - "ApiService", - "CommonService", - "BaseRestService", - function ($rootScope, apiService, commonService, baseService) { - var serviceFactory = Object.create(baseService); - serviceFactory.init("module-post"); - - var _search = async function (objData) { - var data = serviceFactory.parseQuery(objData); - var url = this.prefixUrl; - - if (data) { - url += "/search?"; - url = url.concat(data); - } - var req = { - serviceBase: this.serviceBase, - method: "GET", - url: url, - }; - return await this.getRestApiResult(req); - }; - - var _delete = async function (id) { - var url = this.prefixUrl + "/" + id; - var req = { - method: "DELETE", - url: url, - }; - return await apiService.sendRequest(req); - }; - var _updateInfos = async function (modules) { - var req = { - method: "POST", - url: this.prefixUrl + "/update-infos", - data: JSON.stringify(modules), - }; - return await apiService.sendRequest(req); - }; - serviceFactory.search = _search; - serviceFactory.delete = _delete; - serviceFactory.updateInfos = _updateInfos; - return serviceFactory; - }, -]); - -"use strict"; -app.controller("PageController", [ - "$scope", - "$rootScope", - "ngAppSettings", - "$location", - "$routeParams", - "PageRestService", - "PagePostRestService", - "UrlAliasService", - "RestMixDbTablePortalService", - "RestMixDbDataPortalService", - "RestMixDbColumnPortalService", - "MixDbDataService", - function ( - $scope, - $rootScope, - ngAppSettings, - $location, - $routeParams, - service, - pagePostRestService, - urlAliasService, - databaseService, - dataService, - columnService, - mixDbService - ) { - BaseRestCtrl.call( - this, - $scope, - $rootScope, - $location, - $routeParams, - ngAppSettings, - service - ); - $scope.request.culture = $rootScope.globalSettings.defaultCulture; - var pageModuleService = $rootScope.getRestService("page-module"); - $scope.viewmodelType = "page"; - $scope.request.query = "level=0"; - $scope.pageType = {}; - $scope.pageTypes = $rootScope.globalSettings.pageTypes; - $scope.selectedCategories = []; - $scope.selectedTags = []; - $scope.selectedModules = []; - $scope.pageData = { - posts: [], - products: [], - data: [], - }; - $scope.request.columns = [ - "id", - "title", - "createdDateTime", - "type", - "image", - "detailUrl", - ]; - $scope.additionalData = null; - $scope.temp = null; - $scope.postRequest = angular.copy(ngAppSettings.request); - $scope.additionalDatabaseRequest = angular.copy(ngAppSettings.request); - ($scope.additionalDatabaseRequest.searchColumns = "Type"), - ($scope.additionalDatabaseRequest.compareOperator = "Equal"), - ($scope.additionalDatabaseRequest.keyword = "AdditionalData"); - $scope.canDrag = - $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; - $scope.loadPosts = async function () { + $scope.loadPosts = async function () { $rootScope.isBusy = true; var id = $routeParams.id; $scope.postRequest.query += "&page_id=" + id; @@ -4014,55 +4079,205 @@ app.factory("PagePostRestService", [ ]); "use strict"; -app.controller("OAuthClientController", [ +app.controller("PageGalleryController", [ "$scope", "$rootScope", "ngAppSettings", - "$location", "$routeParams", - "RestOAuthClientService", + "$location", + "PageGalleryService", + "PostRestService", + "ApiService", + "CommonService", function ( $scope, $rootScope, ngAppSettings, - $location, $routeParams, - service + $location, + service, + postService, + apiService, + commonService ) { - BaseRestCtrl.call( + BaseCtrl.call( this, $scope, $rootScope, - $location, $routeParams, ngAppSettings, service ); - + $scope.cates = ["Site", "System"]; + $scope.others = []; + $scope.mixConfigurations = $rootScope.globalSettings; + $scope.pageId = $routeParams.id; $scope.canDrag = $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; - $scope.applicationTypes = ["JavaScript", "NativeConfidential"]; - }, -]); - -"use strict"; -app.factory("RestOAuthClientService", [ - "BaseRestService", - function (baseService) { - var serviceFactory = Object.create(baseService); - serviceFactory.initService("/rest/auth", "oauth-client", true); - return serviceFactory; - }, -]); - -"use strict"; -app.controller("PermissionController", [ - "$scope", - "$rootScope", - "ngAppSettings", - "$routeParams", - "$location", - "ApiService", + $scope.getList = async function () { + $rootScope.isBusy = true; + var id = $routeParams.id; + $scope.request.query = "&page_id=" + id; + var response = await service.getList($scope.request); + $scope.canDrag = + $scope.request.sortBy !== "Priority" || + $scope.request.direction !== "0"; + if (response.success) { + $scope.data = response.data; + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.remove = function (pageId, postId) { + $rootScope.showConfirm( + $scope, + "removeConfirmed", + [pageId, postId], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + + $scope.removeConfirmed = async function (pageId, postId) { + $rootScope.isBusy = true; + var result = await service.delete(pageId, postId); + if (result.success) { + if ($scope.removeCallback) { + $rootScope.executeFunctionByName( + "removeCallback", + $scope.removeCallbackArgs, + $scope + ); + } + $scope.getList(); + } else { + $rootScope.showMessage("failed"); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + + $scope.saveOthers = async function () { + var response = await service.saveList($scope.others); + if (response.success) { + $scope.getList(); + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.updateInfos = async function (index) { + $scope.data.items.splice(index, 1); + $rootScope.isBusy = true; + var startIndex = $scope.data.items[0].priority - 1; + for (var i = 0; i < $scope.data.items.length; i++) { + $scope.data.items[i].priority = startIndex + i + 1; + } + var resp = await service.updateInfos($scope.data.items); + if (resp && resp.success) { + $scope.activedPage = resp.data; + $rootScope.showMessage("success", "success"); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + }, +]); + +"use strict"; +app.factory("PageGalleryService", [ + "$rootScope", + "ApiService", + "CommonService", + "BaseService", + function ($rootScope, apiService, commonService, baseService) { + var serviceFactory = Object.create(baseService); + serviceFactory.init("page-post"); + var _delete = async function (pageId, postId) { + var url = this.prefixUrl + "/delete/" + pageId + "/" + postId; + var req = { + method: "GET", + url: url, + }; + return await apiService.sendRequest(req); + }; + var _updateInfos = async function (pages) { + var req = { + method: "POST", + url: this.prefixUrl + "/update-infos", + data: JSON.stringify(pages), + }; + return await apiService.sendRequest(req); + }; + serviceFactory.delete = _delete; + serviceFactory.updateInfos = _updateInfos; + return serviceFactory; + }, +]); + +"use strict"; +app.controller("OAuthClientController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$location", + "$routeParams", + "RestOAuthClientService", + function ( + $scope, + $rootScope, + ngAppSettings, + $location, + $routeParams, + service + ) { + BaseRestCtrl.call( + this, + $scope, + $rootScope, + $location, + $routeParams, + ngAppSettings, + service + ); + + $scope.canDrag = + $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; + $scope.applicationTypes = ["JavaScript", "NativeConfidential"]; + }, +]); + +"use strict"; +app.factory("RestOAuthClientService", [ + "BaseRestService", + function (baseService) { + var serviceFactory = Object.create(baseService); + serviceFactory.initService("/rest/auth", "oauth-client", true); + return serviceFactory; + }, +]); + +"use strict"; +app.controller("PermissionController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$routeParams", + "$location", + "ApiService", "CommonService", "PermissionService", "RestPortalPageNavigationService", @@ -4203,213 +4418,63 @@ app.factory("RestPortalPageNavigationService", [ ]); "use strict"; -app.controller("PageGalleryController", [ +app.controller("PostController", [ "$scope", "$rootScope", + "$location", + "$filter", "ngAppSettings", "$routeParams", - "$location", - "PageGalleryService", "PostRestService", - "ApiService", - "CommonService", + "UrlAliasService", + "RestMixDbDataPortalService", + "RestMixDbColumnPortalService", + "RestRelatedAttributeDataPortalService", + "RestMixDbTablePortalService", + "MixDbDataService", function ( $scope, $rootScope, + $location, + $filter, ngAppSettings, $routeParams, - $location, service, - postService, - apiService, - commonService + urlAliasService, + dataService, + columnService, + navService, + databaseService, + mixDbService ) { - BaseCtrl.call( + BaseRestCtrl.call( this, $scope, $rootScope, + $location, $routeParams, ngAppSettings, service ); - $scope.cates = ["Site", "System"]; - $scope.others = []; - $scope.mixConfigurations = $rootScope.globalSettings; - $scope.pageId = $routeParams.id; - $scope.canDrag = - $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; - $scope.getList = async function () { - $rootScope.isBusy = true; - var id = $routeParams.id; - $scope.request.query = "&page_id=" + id; - var response = await service.getList($scope.request); - $scope.canDrag = - $scope.request.sortBy !== "Priority" || - $scope.request.direction !== "0"; - if (response.success) { - $scope.data = response.data; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.remove = function (pageId, postId) { - $rootScope.showConfirm( - $scope, - "removeConfirmed", - [pageId, postId], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); + if (!$scope.referrerUrl) { + $scope.referrerUrl = "/admin/post/list"; + } + $scope.request.searchColumns = "title"; + $scope.request.culture = $rootScope.globalSettings.defaultCulture; + $scope.request.queries = []; + $scope.request.metadataQueries = []; + $scope.defaultQuery = { + fieldName: "", + compareOperator: "Equal", + value: "", }; - - $scope.removeConfirmed = async function (pageId, postId) { - $rootScope.isBusy = true; - var result = await service.delete(pageId, postId); - if (result.success) { - if ($scope.removeCallback) { - $rootScope.executeFunctionByName( - "removeCallback", - $scope.removeCallbackArgs, - $scope - ); - } - $scope.getList(); - } else { - $rootScope.showMessage("failed"); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - - $scope.saveOthers = async function () { - var response = await service.saveList($scope.others); - if (response.success) { - $scope.getList(); - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.updateInfos = async function (index) { - $scope.data.items.splice(index, 1); - $rootScope.isBusy = true; - var startIndex = $scope.data.items[0].priority - 1; - for (var i = 0; i < $scope.data.items.length; i++) { - $scope.data.items[i].priority = startIndex + i + 1; - } - var resp = await service.updateInfos($scope.data.items); - if (resp && resp.success) { - $scope.activedPage = resp.data; - $rootScope.showMessage("success", "success"); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - }, -]); - -"use strict"; -app.factory("PageGalleryService", [ - "$rootScope", - "ApiService", - "CommonService", - "BaseService", - function ($rootScope, apiService, commonService, baseService) { - var serviceFactory = Object.create(baseService); - serviceFactory.init("page-post"); - var _delete = async function (pageId, postId) { - var url = this.prefixUrl + "/delete/" + pageId + "/" + postId; - var req = { - method: "GET", - url: url, - }; - return await apiService.sendRequest(req); - }; - var _updateInfos = async function (pages) { - var req = { - method: "POST", - url: this.prefixUrl + "/update-infos", - data: JSON.stringify(pages), - }; - return await apiService.sendRequest(req); - }; - serviceFactory.delete = _delete; - serviceFactory.updateInfos = _updateInfos; - return serviceFactory; - }, -]); - -"use strict"; -app.controller("PostController", [ - "$scope", - "$rootScope", - "$location", - "$filter", - "ngAppSettings", - "$routeParams", - "PostRestService", - "UrlAliasService", - "RestMixDbDataPortalService", - "RestMixDbColumnPortalService", - "RestRelatedAttributeDataPortalService", - "RestMixDbTablePortalService", - "MixDbDataService", - function ( - $scope, - $rootScope, - $location, - $filter, - ngAppSettings, - $routeParams, - service, - urlAliasService, - dataService, - columnService, - navService, - databaseService, - mixDbService - ) { - BaseRestCtrl.call( - this, - $scope, - $rootScope, - $location, - $routeParams, - ngAppSettings, - service - ); - if (!$scope.referrerUrl) { - $scope.referrerUrl = "/admin/post/list"; - } - $scope.request.searchColumns = "title"; - $scope.request.culture = $rootScope.globalSettings.defaultCulture; - $scope.request.queries = []; - $scope.request.metadataQueries = []; - $scope.defaultQuery = { - fieldName: "", - compareOperator: "Equal", - value: "", - }; - $scope.viewmodelType = "post"; - $scope.additionalData = {}; - $scope.createUrl = "/admin/post/create?"; - $scope.postTypeRequest = angular.copy(ngAppSettings.request); - ($scope.postTypeRequest.searchColumns = "Type"), - ($scope.postTypeRequest.compareOperator = "Equal"), - ($scope.postTypeRequest.keyword = "AdditionalData"); + $scope.viewmodelType = "post"; + $scope.additionalData = {}; + $scope.createUrl = "/admin/post/create?"; + $scope.postTypeRequest = angular.copy(ngAppSettings.request); + ($scope.postTypeRequest.searchColumns = "Type"), + ($scope.postTypeRequest.compareOperator = "Equal"), + ($scope.postTypeRequest.keyword = "AdditionalData"); $scope.initList = async function () { if ($routeParams.template) { @@ -5042,215 +5107,58 @@ app.factory("RoleService", [ ]); "use strict"; -app.controller("ServiceController", [ +app.controller("SchedulerController", [ "$scope", "$rootScope", - "ngAppSettings", "$routeParams", "$location", - "RestMixDbTablePortalService", - "ApiService", - "CommonService", - function ( - $scope, - $rootScope, - ngAppSettings, - $routeParams, - $location, - service, - commonService - ) { - BaseODataCtrl.call( - this, - $scope, - $rootScope, - $routeParams, - ngAppSettings, - service - ); - $scope.defaultId = "default"; - $scope.parentId = null; - $scope.parentType = null; - $scope.cates = ["Site", "System"]; - $scope.others = []; - $scope.mixConfigurations = $rootScope.globalSettings; - $scope.canDrag = - $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; - $scope.init = async function () { - $scope.mixDbTableId = $routeParams.mixDbTableId; - $scope.mixDbTableName = $routeParams.mixDbTableName; - $scope.dataContentId = $routeParams.dataContentId; - }; - $scope.saveSuccessCallback = function () { - $rootScope.isBusy = false; - $scope.$apply(); - // if($scope.parentId){ - // $location.url('/admin/mix-db-data/details?dataContentId='+ $scope.parentId); - // } - // else{ - // $location.url('/admin/mix-db-data/list?mixDbTableId='+ $scope.viewmodel.mixDbTableId); - // } + "SchedulerService", + function ($scope, $rootScope, $routeParams, $location, service) { + $scope.jobs = []; + $scope.intervalTypes = [ + "Second", + "Minute", + "Hour", + "Day", + "Week", + "Month", + "Year", + ]; + $scope.templates = { + "Mix.Scheduler.Jobs.KeepPoolAliveJob": { + domain: "https://example.com", + }, + "Mix.Scheduler.Jobs.PublishScheduledPostsJob": {}, + "Mix.Scheduler.Jobs.SendMessageQueueJob": { + data: { + topic: "", + action: "", + data: {}, + }, + }, + "Mix.Scheduler.Jobs.SendPortalMessageJob": { + data: { + topic: "", + action: "", + data: "", + }, + }, }; - $scope.getList = async function () { - $rootScope.isBusy = true; - $scope.mixDbTableId = $routeParams.mixDbTableId; - $scope.mixDbTableName = $routeParams.mixDbTableName; - var type = $routeParams.type; - var parentId = $routeParams.parentId; - var response = await service.getList( - "read", - $scope.request, - $scope.mixDbTableId, - $scope.mixDbTableName, - type, - parentId - ); - $scope.canDrag = - $scope.request.sortBy !== "Priority" || - $scope.request.direction !== "0"; - if (response) { - $scope.data = response; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors("Failed"); - $rootScope.isBusy = false; - $scope.$apply(); + + $scope.updateMessageTemplate = () => { + if ($scope.templates[$scope.schedule.jobName]) { + $scope.schedule.jobData = null; + setTimeout(() => { + $scope.schedule.jobData = $scope.templates[$scope.schedule.jobName]; + $scope.$apply(); + }, 200); } }; - $scope.getSingle = async function () { - $rootScope.isBusy = true; - var id = $routeParams.id || $scope.defaultId; - $scope.mixDbTableId = $routeParams.mixDbTableId; - $scope.mixDbTableName = $routeParams.mixDbTableName; - var resp = await service.getSingle("portal", [ - id, - $scope.mixDbTableId, - $scope.mixDbTableName, - ]); - if (resp) { - $scope.viewmodel = resp; - $scope.viewmodel.parentType = $scope.parentType; - $scope.viewmodel.parentId = $scope.parentId; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors("Failed"); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.preview = function (item) { - item.editUrl = "/admin/post/details/" + item.id; - $rootScope.preview("post", item, item.title, "modal-lg"); - }; - $scope.edit = function (data) { - $scope.goToPath( - "/admin/mix-db-data/details?dataContentId=" + - data.id + - "&mixDbTableId=" + - $scope.mixDbTableId - ); - }; - $scope.remove = function (data) { - $rootScope.showConfirm( - $scope, - "removeConfirmed", - [data.id], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); - }; - - $scope.removeConfirmed = async function (dataContentId) { - $rootScope.isBusy = true; - var result = await service.delete([dataContentId]); - if (result.success) { - if ($scope.removeCallback) { - $rootScope.executeFunctionByName( - "removeCallback", - $scope.removeCallbackArgs, - $scope - ); - } - $scope.getList(); - } else { - $rootScope.showErrors(result.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - - $scope.saveOthers = async function () { - var response = await service.saveList($scope.others); - if (response.success) { - $scope.getList(); - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - }, -]); - -"use strict"; -app.controller("SchedulerController", [ - "$scope", - "$rootScope", - "$routeParams", - "$location", - "SchedulerService", - function ($scope, $rootScope, $routeParams, $location, service) { - $scope.jobs = []; - $scope.intervalTypes = [ - "Second", - "Minute", - "Hour", - "Day", - "Week", - "Month", - "Year", - ]; - $scope.templates = { - "Mix.Scheduler.Jobs.KeepPoolAliveJob": { - domain: "https://example.com", - }, - "Mix.Scheduler.Jobs.PublishScheduledPostsJob": {}, - "Mix.Scheduler.Jobs.SendMessageQueueJob": { - data: { - topic: "", - action: "", - data: {}, - }, - }, - "Mix.Scheduler.Jobs.SendPortalMessageJob": { - data: { - topic: "", - action: "", - data: "", - }, - }, - }; - - $scope.updateMessageTemplate = () => { - if ($scope.templates[$scope.schedule.jobName]) { - $scope.schedule.jobData = null; - setTimeout(() => { - $scope.schedule.jobData = $scope.templates[$scope.schedule.jobName]; - $scope.$apply(); - }, 200); - } - }; - $scope.init = function () { - $scope.getTriggers(); - $scope.getJobs(); - }; - + $scope.init = function () { + $scope.getTriggers(); + $scope.getJobs(); + }; + $scope.getSingle = async function () { $scope.getJobs(); $scope.getTrigger(); @@ -5577,73 +5485,230 @@ app.factory("SchedulerService", [ ]); "use strict"; -app.controller("SocialFeedController", [ - "$rootScope", +app.controller("ServiceController", [ "$scope", - "$http", - "PostRestService", - function ($rootScope, $scope, $http, postService) { - $scope.types = ["Facebook", "Instagram"]; - $scope.isInit = false; - $scope.defaultPost = null; - $scope.defaultProperty = { - name: null, - dataType: 7, - value: "", + "$rootScope", + "ngAppSettings", + "$routeParams", + "$location", + "RestMixDbTablePortalService", + "ApiService", + "CommonService", + function ( + $scope, + $rootScope, + ngAppSettings, + $routeParams, + $location, + service, + commonService + ) { + BaseODataCtrl.call( + this, + $scope, + $rootScope, + $routeParams, + ngAppSettings, + service + ); + $scope.defaultId = "default"; + $scope.parentId = null; + $scope.parentType = null; + $scope.cates = ["Site", "System"]; + $scope.others = []; + $scope.mixConfigurations = $rootScope.globalSettings; + $scope.canDrag = + $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; + $scope.init = async function () { + $scope.mixDbTableId = $routeParams.mixDbTableId; + $scope.mixDbTableName = $routeParams.mixDbTableName; + $scope.dataContentId = $routeParams.dataContentId; }; - $scope.data = []; - $scope.errors = []; - $scope.socialSettings = { - app_id: null, - page_id: null, - app_secret: null, - access_token: "", - page: [], - data: [], - posts: [], - show_login: true, - errors: [], + $scope.saveSuccessCallback = function () { + $rootScope.isBusy = false; + $scope.$apply(); + // if($scope.parentId){ + // $location.url('/admin/mix-db-data/details?dataContentId='+ $scope.parentId); + // } + // else{ + // $location.url('/admin/mix-db-data/list?mixDbTableId='+ $scope.viewmodel.mixDbTableId); + // } }; - $scope.init = async function () { - window.fbAsyncInit = function () { - FB.init({ - appId: $rootScope.getConfiguration("FacebookAppId"), - autoLogAppEvents: true, - xfbml: true, - version: "v3.2", - }); - }; - $scope.socialSettings = { - app_id: $rootScope.mixConfigurations.data.FacebookAppId, - page_id: $rootScope.mixConfigurations.data.Facebook_Page_Id, - app_secret: $rootScope.mixConfigurations.data.FacebookAppSecret, - access_token: $rootScope.mixConfigurations.data.FacebookAccessToken, - show_login: true, - errors: [], - }; - if ($scope.socialSettings.access_token) { - $scope.socialSettings.show_login = false; - $scope.loadPages(); + $scope.getList = async function () { + $rootScope.isBusy = true; + $scope.mixDbTableId = $routeParams.mixDbTableId; + $scope.mixDbTableName = $routeParams.mixDbTableName; + var type = $routeParams.type; + var parentId = $routeParams.parentId; + var response = await service.getList( + "read", + $scope.request, + $scope.mixDbTableId, + $scope.mixDbTableName, + type, + parentId + ); + $scope.canDrag = + $scope.request.sortBy !== "Priority" || + $scope.request.direction !== "0"; + if (response) { + $scope.data = response; + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors("Failed"); + $rootScope.isBusy = false; + $scope.$apply(); } - postService.getSingle(["portal"]).then((resp) => { - $scope.defaultPost = resp.data; - }); }; - - // This function is called when someone finishes with the Login - // Button. See the onlogin handler attached to it in the sample - // code below. - $scope.login = function () { - FB.login( - function (response) { - // handle the response - $scope.statusChangeCallback(response); - }, - { - scope: "email, manage_pages", - return_scopes: true, - } - ); + $scope.getSingle = async function () { + $rootScope.isBusy = true; + var id = $routeParams.id || $scope.defaultId; + $scope.mixDbTableId = $routeParams.mixDbTableId; + $scope.mixDbTableName = $routeParams.mixDbTableName; + var resp = await service.getSingle("portal", [ + id, + $scope.mixDbTableId, + $scope.mixDbTableName, + ]); + if (resp) { + $scope.viewmodel = resp; + $scope.viewmodel.parentType = $scope.parentType; + $scope.viewmodel.parentId = $scope.parentId; + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors("Failed"); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.preview = function (item) { + item.editUrl = "/admin/post/details/" + item.id; + $rootScope.preview("post", item, item.title, "modal-lg"); + }; + $scope.edit = function (data) { + $scope.goToPath( + "/admin/mix-db-data/details?dataContentId=" + + data.id + + "&mixDbTableId=" + + $scope.mixDbTableId + ); + }; + $scope.remove = function (data) { + $rootScope.showConfirm( + $scope, + "removeConfirmed", + [data.id], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + + $scope.removeConfirmed = async function (dataContentId) { + $rootScope.isBusy = true; + var result = await service.delete([dataContentId]); + if (result.success) { + if ($scope.removeCallback) { + $rootScope.executeFunctionByName( + "removeCallback", + $scope.removeCallbackArgs, + $scope + ); + } + $scope.getList(); + } else { + $rootScope.showErrors(result.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + + $scope.saveOthers = async function () { + var response = await service.saveList($scope.others); + if (response.success) { + $scope.getList(); + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + }, +]); + +"use strict"; +app.controller("SocialFeedController", [ + "$rootScope", + "$scope", + "$http", + "PostRestService", + function ($rootScope, $scope, $http, postService) { + $scope.types = ["Facebook", "Instagram"]; + $scope.isInit = false; + $scope.defaultPost = null; + $scope.defaultProperty = { + name: null, + dataType: 7, + value: "", + }; + $scope.data = []; + $scope.errors = []; + $scope.socialSettings = { + app_id: null, + page_id: null, + app_secret: null, + access_token: "", + page: [], + data: [], + posts: [], + show_login: true, + errors: [], + }; + $scope.init = async function () { + window.fbAsyncInit = function () { + FB.init({ + appId: $rootScope.getConfiguration("FacebookAppId"), + autoLogAppEvents: true, + xfbml: true, + version: "v3.2", + }); + }; + $scope.socialSettings = { + app_id: $rootScope.mixConfigurations.data.FacebookAppId, + page_id: $rootScope.mixConfigurations.data.Facebook_Page_Id, + app_secret: $rootScope.mixConfigurations.data.FacebookAppSecret, + access_token: $rootScope.mixConfigurations.data.FacebookAccessToken, + show_login: true, + errors: [], + }; + if ($scope.socialSettings.access_token) { + $scope.socialSettings.show_login = false; + $scope.loadPages(); + } + postService.getSingle(["portal"]).then((resp) => { + $scope.defaultPost = resp.data; + }); + }; + + // This function is called when someone finishes with the Login + // Button. See the onlogin handler attached to it in the sample + // code below. + $scope.login = function () { + FB.login( + function (response) { + // handle the response + $scope.statusChangeCallback(response); + }, + { + scope: "email, manage_pages", + return_scopes: true, + } + ); }; $scope.statusChangeCallback = function (response) { @@ -6096,54 +6161,6 @@ app.controller("TemplateController", [ }, ]); -"use strict"; -app.controller("TenantController", [ - "$scope", - "$rootScope", - "ngAppSettings", - "$location", - "$routeParams", - "TenantRestService", - function ( - $scope, - $rootScope, - ngAppSettings, - $location, - $routeParams, - service - ) { - BaseRestCtrl.call( - this, - $scope, - $rootScope, - $location, - $routeParams, - ngAppSettings, - service - ); - $scope.request.columns = [ - "id", - "displayName", - "systemName", - "primaryDomain", - "createdDateTime", - "createdBy", - ]; - $scope.canDrag = - $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; - }, -]); - -"use strict"; -app.factory("TenantRestService", [ - "BaseRestService", - function (baseService) { - var serviceFactory = Object.create(baseService); - serviceFactory.init("mix-tenant"); - return serviceFactory; - }, -]); - "use strict"; app.controller("ThemeController", [ "$scope", @@ -6294,6 +6311,54 @@ app.controller("ThemeController", [ }, ]); +"use strict"; +app.controller("TenantController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$location", + "$routeParams", + "TenantRestService", + function ( + $scope, + $rootScope, + ngAppSettings, + $location, + $routeParams, + service + ) { + BaseRestCtrl.call( + this, + $scope, + $rootScope, + $location, + $routeParams, + ngAppSettings, + service + ); + $scope.request.columns = [ + "id", + "displayName", + "systemName", + "primaryDomain", + "createdDateTime", + "createdBy", + ]; + $scope.canDrag = + $scope.request.sortBy !== "Priority" || $scope.request.direction !== "0"; + }, +]); + +"use strict"; +app.factory("TenantRestService", [ + "BaseRestService", + function (baseService) { + var serviceFactory = Object.create(baseService); + serviceFactory.init("mix-tenant"); + return serviceFactory; + }, +]); + "use strict"; app.controller("UserController", [ "$scope", @@ -7249,69 +7314,50 @@ app.component("appSettingsAuth", { }, }); -app.component("appSettingsGeneral", { +app.component("appSettingsDefault", { templateUrl: - "/mix-app/views/app-portal/pages/app-settings/components/general/view.html", + "/mix-app/views/app-portal/pages/app-settings/components/default/view.html", controller: [ "$rootScope", - "$scope", - "CryptoService", - "CommonService", - function ($rootScope, $scope, cryptoService, commonService) { + "ngAppSettings", + function ($rootScope, ngAppSettings) { var ctrl = this; - ctrl.$onInit = () => { - var key = cryptoService.parseKeys(ctrl.appSettings.apiEncryptKey); - ctrl.apiKey = key.key; - ctrl.iv = key.iv; + ctrl.$onInit = function () { + ctrl.properties = $.parseJSON( + ctrl.appSettings.AppSettings.DefaultPostAttr + ); + ctrl.trackedProperties = $.parseJSON( + ctrl.appSettings.AppSettings.DefaultPostAttr + ); + ctrl.dataTypes = $rootScope.globalSettings.dataTypes; }; - ctrl.stopApplication = async function () { - $rootScope.isBusy = true; - await commonService.stopApplication(); - $rootScope.showMessage("success", "success"); - $rootScope.isBusy = false; - $scope.$apply(); + ctrl.addPostProperty = function () { + ctrl.properties.push({ + priority: 0, + name: "", + value: null, + dataType: "7", + }); }; + ctrl.$doCheck = function () { + if (ctrl.trackedProperties != ctrl.properties) { + ctrl.trackedProperties = angular.copy(ctrl.properties); + ctrl.appSettings.AppSettings.DefaultPostAttr = JSON.stringify( + ctrl.properties + ); + } + }.bind(ctrl); }, ], bindings: { appSettings: "=", + cultures: "=", + statuses: "=", onDelete: "&", onUpdate: "&", }, }); -modules.component("portalMenus", { - templateUrl: - "/mix-app/views/app-portal/pages/app-settings/components/portal-menus/view.html", - bindings: { - data: "=", - allowedTypes: "=", - }, - controller: [ - "$rootScope", - "$scope", - "$location", - "ApiService", - "CommonService", - "ngAppSettings", - function ( - $rootScope, - $scope, - $location, - apiService, - commonService, - ngAppSettings - ) { - var ctrl = this; - // ctrl.icons = []; - ctrl.translate = $rootScope.translate; - ctrl.init = function () { - ctrl.icons = ngAppSettings.icons; - }; - }, - ], -}); - app.component("appSettingsHeart", { templateUrl: "/mix-app/views/app-portal/pages/app-settings/components/heart/view.html", @@ -7349,45 +7395,32 @@ app.component("appSettingsHeart", { ], }); -app.component("appSettingsDefault", { +app.component("appSettingsGeneral", { templateUrl: - "/mix-app/views/app-portal/pages/app-settings/components/default/view.html", + "/mix-app/views/app-portal/pages/app-settings/components/general/view.html", controller: [ "$rootScope", - "ngAppSettings", - function ($rootScope, ngAppSettings) { + "$scope", + "CryptoService", + "CommonService", + function ($rootScope, $scope, cryptoService, commonService) { var ctrl = this; - ctrl.$onInit = function () { - ctrl.properties = $.parseJSON( - ctrl.appSettings.AppSettings.DefaultPostAttr - ); - ctrl.trackedProperties = $.parseJSON( - ctrl.appSettings.AppSettings.DefaultPostAttr - ); - ctrl.dataTypes = $rootScope.globalSettings.dataTypes; + ctrl.$onInit = () => { + var key = cryptoService.parseKeys(ctrl.appSettings.apiEncryptKey); + ctrl.apiKey = key.key; + ctrl.iv = key.iv; }; - ctrl.addPostProperty = function () { - ctrl.properties.push({ - priority: 0, - name: "", - value: null, - dataType: "7", - }); + ctrl.stopApplication = async function () { + $rootScope.isBusy = true; + await commonService.stopApplication(); + $rootScope.showMessage("success", "success"); + $rootScope.isBusy = false; + $scope.$apply(); }; - ctrl.$doCheck = function () { - if (ctrl.trackedProperties != ctrl.properties) { - ctrl.trackedProperties = angular.copy(ctrl.properties); - ctrl.appSettings.AppSettings.DefaultPostAttr = JSON.stringify( - ctrl.properties - ); - } - }.bind(ctrl); }, ], bindings: { appSettings: "=", - cultures: "=", - statuses: "=", onDelete: "&", onUpdate: "&", }, @@ -7403,6 +7436,38 @@ app.component("customerMain", { }, }); +modules.component("portalMenus", { + templateUrl: + "/mix-app/views/app-portal/pages/app-settings/components/portal-menus/view.html", + bindings: { + data: "=", + allowedTypes: "=", + }, + controller: [ + "$rootScope", + "$scope", + "$location", + "ApiService", + "CommonService", + "ngAppSettings", + function ( + $rootScope, + $scope, + $location, + apiService, + commonService, + ngAppSettings + ) { + var ctrl = this; + // ctrl.icons = []; + ctrl.translate = $rootScope.translate; + ctrl.init = function () { + ctrl.icons = ngAppSettings.icons; + }; + }, + ], +}); + app.component("customerOrders", { templateUrl: "/mix-app/views/app-portal/pages/customer/components/orders/customer-orders.html", @@ -7442,6 +7507,21 @@ app.component("customerOrders", { }, }); +app.component("mixDatabaseEdm", { + templateUrl: + "/mix-app/views/app-portal/pages/mix-db-table/components/edm/view.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.mixConfigurations = $rootScope.globalSettings; + }, + ], + bindings: { + model: "=", + }, +}); + app.component("appSettingsSmtp", { templateUrl: "/mix-app/views/app-portal/pages/app-settings/components/smtp/view.html", @@ -7456,6 +7536,44 @@ app.component("appSettingsSmtp", { }, }); +app.component("mixDatabaseMain", { + templateUrl: + "/mix-app/views/app-portal/pages/mix-db-table/components/main/view.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + + ctrl.$onInit = () => { + ctrl.globalSettings = $rootScope.globalSettings; + ctrl.isInRole = $rootScope.isInRole; + }; + ctrl.gennerateName = function () { + if ( + !ctrl.model.id || + ctrl.model.systemName === null || + ctrl.model.systemName === "" + ) { + let prefix = ctrl.model.type == "System" ? "sys" : ""; + ctrl.model.systemName = $rootScope.generateKeyword( + `${prefix} ${ctrl.model.displayName}`, + ctrl.model.namingConvention == "TitleCase" ? "" : "_", + ctrl.model.namingConvention == "TitleCase", + true + ); + if (ctrl.schema) { + ctrl.model.systemName = `${ctrl.schema}${ctrl.model.systemName}`; + } + } + }; + }, + ], + bindings: { + model: "=", + schema: "=?", + }, +}); + app.component("mixDbTables", { bindings: { model: "=", @@ -7565,21 +7683,6 @@ app.component("moduleContent", { ], }); -app.component("moduleType", { - templateUrl: - "/mix-app/views/app-portal/pages/module/components/module-type/view.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - ctrl.mixConfigurations = $rootScope.globalSettings; - }, - ], - bindings: { - model: "=", - }, -}); - app.component("moduleAdvanced", { templateUrl: "/mix-app/views/app-portal/pages/module/components/module-advanced/view.html", @@ -7599,9 +7702,9 @@ app.component("moduleAdvanced", { ], }); -app.component("mixDatabaseEdm", { +app.component("moduleType", { templateUrl: - "/mix-app/views/app-portal/pages/mix-db-table/components/edm/view.html", + "/mix-app/views/app-portal/pages/module/components/module-type/view.html", controller: [ "$rootScope", function ($rootScope) { @@ -7614,44 +7717,6 @@ app.component("mixDatabaseEdm", { }, }); -app.component("mixDatabaseMain", { - templateUrl: - "/mix-app/views/app-portal/pages/mix-db-table/components/main/view.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - - ctrl.$onInit = () => { - ctrl.globalSettings = $rootScope.globalSettings; - ctrl.isInRole = $rootScope.isInRole; - }; - ctrl.gennerateName = function () { - if ( - !ctrl.model.id || - ctrl.model.systemName === null || - ctrl.model.systemName === "" - ) { - let prefix = ctrl.model.type == "System" ? "sys" : ""; - ctrl.model.systemName = $rootScope.generateKeyword( - `${prefix} ${ctrl.model.displayName}`, - ctrl.model.namingConvention == "TitleCase" ? "" : "_", - ctrl.model.namingConvention == "TitleCase", - true - ); - if (ctrl.schema) { - ctrl.model.systemName = `${ctrl.schema}${ctrl.model.systemName}`; - } - } - }; - }, - ], - bindings: { - model: "=", - schema: "=?", - }, -}); - app.component("pageGeneral", { templateUrl: "/mix-app/views/app-portal/pages/page/components/general/general.html", @@ -7759,10 +7824,55 @@ app.component("pageGeneral", { }, }); -app.component("pageMain", { - templateUrl: "/mix-app/views/app-portal/pages/page/components/main/main.html", - controller: [ - "$rootScope", +app.component("pageModules", { + templateUrl: + "/mix-app/views/app-portal/pages/page/components/modules/modules.html", + bindings: { + page: "=", + onDelete: "&?", + onUpdate: "&?", + }, + controller: [ + "$scope", + "ngAppSettings", + "ModuleRestService", + function ($scope, ngAppSettings, moduleService) { + var ctrl = this; + ctrl.modules = []; + ctrl.request = angular.copy(ngAppSettings.request); + + ctrl.$onInit = async () => { + ctrl.request.columns = [ + "id", + "title", + "systemName", + "createdDateTime", + "type", + ]; + ctrl.request.culture = ctrl.page.specificulture; + ctrl.loadModules(); + }; + ctrl.loadModules = async () => { + let getModules = await moduleService.getList(ctrl.request); + if (getModules.success) { + ctrl.modules = getModules.data.items; + $scope.$apply(); + } + }; + ctrl.select = async (associations) => { + ctrl.associations = associations; + if (ctrl.onUpdate) { + ctrl.onUpdate({ associations: associations }); + } + }; + }, + ], +}); + +app.component("pageMain", { + templateUrl: "/mix-app/views/app-portal/pages/page/components/main/main.html", + controller: [ + "$rootScope", "$scope", "ngAppSettings", function ($rootScope, $scope) { @@ -7823,96 +7933,6 @@ app.component("pageAdvanced", { ], }); -app.component("pageContent", { - templateUrl: - "/mix-app/views/app-portal/pages/page/components/page-content/view.html", - bindings: { - additionalData: "=", - model: "=", - }, - controller: [ - "$rootScope", - "$scope", - function ($rootScope, $scope) { - var ctrl = this; - ctrl.translate = $rootScope.translate; - ctrl.$onInit = function () { - ctrl.backUrl = `/admin/page/details`; - }; - ctrl.generateSeo = function () { - if ($scope.viewmodel) { - if (ctrl.model.seoName === null || ctrl.model.seoName === "") { - ctrl.model.seoName = $rootScope.generateKeyword( - ctrl.model.title, - "-" - ); - } - if (ctrl.model.seoTitle === null || ctrl.model.seoTitle === "") { - ctrl.model.seoTitle = ctrl.model.title; - } - if ( - ctrl.model.seoDescription === null || - ctrl.model.seoDescription === "" - ) { - ctrl.model.seoDescription = ctrl.model.excerpt; - } - if ( - ctrl.model.seoKeywords === null || - ctrl.model.seoKeywords === "" - ) { - ctrl.model.seoKeywords = ctrl.model.title; - } - } - }; - }, - ], -}); - -app.component("pageModules", { - templateUrl: - "/mix-app/views/app-portal/pages/page/components/modules/modules.html", - bindings: { - page: "=", - onDelete: "&?", - onUpdate: "&?", - }, - controller: [ - "$scope", - "ngAppSettings", - "ModuleRestService", - function ($scope, ngAppSettings, moduleService) { - var ctrl = this; - ctrl.modules = []; - ctrl.request = angular.copy(ngAppSettings.request); - - ctrl.$onInit = async () => { - ctrl.request.columns = [ - "id", - "title", - "systemName", - "createdDateTime", - "type", - ]; - ctrl.request.culture = ctrl.page.specificulture; - ctrl.loadModules(); - }; - ctrl.loadModules = async () => { - let getModules = await moduleService.getList(ctrl.request); - if (getModules.success) { - ctrl.modules = getModules.data.items; - $scope.$apply(); - } - }; - ctrl.select = async (associations) => { - ctrl.associations = associations; - if (ctrl.onUpdate) { - ctrl.onUpdate({ associations: associations }); - } - }; - }, - ], -}); - app.component("pageType", { templateUrl: "/mix-app/views/app-portal/pages/page/components/page-type/view.html", @@ -7928,16 +7948,6 @@ app.component("pageType", { ], }); -app.component("pageParents", { - templateUrl: - "/mix-app/views/app-portal/pages/page/components/parents/parents.html", - bindings: { - page: "=", - onDelete: "&", - onUpdate: "&", - }, -}); - app.component("pagePlugPlay", { templateUrl: "/mix-app/views/app-portal/pages/page/components/plug-play/plug-play.html", @@ -7948,17 +7958,9 @@ app.component("pagePlugPlay", { }, }); -app.component("pageSeo", { - templateUrl: "/mix-app/views/app-portal/pages/page/components/seo/seo.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - ctrl.translate = function (keyword) { - return $rootScope.translate(keyword); - }; - }, - ], +app.component("pageParents", { + templateUrl: + "/mix-app/views/app-portal/pages/page/components/parents/parents.html", bindings: { page: "=", onDelete: "&", @@ -8002,6 +8004,69 @@ app.component("productRelated", { }, }); +app.component("pageSeo", { + templateUrl: "/mix-app/views/app-portal/pages/page/components/seo/seo.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.translate = function (keyword) { + return $rootScope.translate(keyword); + }; + }, + ], + bindings: { + page: "=", + onDelete: "&", + onUpdate: "&", + }, +}); + +app.component("pageContent", { + templateUrl: + "/mix-app/views/app-portal/pages/page/components/page-content/view.html", + bindings: { + additionalData: "=", + model: "=", + }, + controller: [ + "$rootScope", + "$scope", + function ($rootScope, $scope) { + var ctrl = this; + ctrl.translate = $rootScope.translate; + ctrl.$onInit = function () { + ctrl.backUrl = `/admin/page/details`; + }; + ctrl.generateSeo = function () { + if ($scope.viewmodel) { + if (ctrl.model.seoName === null || ctrl.model.seoName === "") { + ctrl.model.seoName = $rootScope.generateKeyword( + ctrl.model.title, + "-" + ); + } + if (ctrl.model.seoTitle === null || ctrl.model.seoTitle === "") { + ctrl.model.seoTitle = ctrl.model.title; + } + if ( + ctrl.model.seoDescription === null || + ctrl.model.seoDescription === "" + ) { + ctrl.model.seoDescription = ctrl.model.excerpt; + } + if ( + ctrl.model.seoKeywords === null || + ctrl.model.seoKeywords === "" + ) { + ctrl.model.seoKeywords = ctrl.model.title; + } + } + }; + }, + ], +}); + app.component("permissionMain", { templateUrl: "/mix-app/views/app-portal/pages/permission/components/main/main.html", @@ -8139,6 +8204,16 @@ app.component("permissionPlugPlay", { ], }); +app.component("permissionParents", { + templateUrl: + "/mix-app/views/app-portal/pages/permission/components/parents/parents.html", + bindings: { + page: "=", + onDelete: "&", + onUpdate: "&", + }, +}); + modules.component("postFilterList", { templateUrl: "/mix-app/views/app-portal/pages/post/components/filter-list/filter-list.html", @@ -8229,16 +8304,6 @@ modules.component("postFilterList", { ], }); -app.component("permissionParents", { - templateUrl: - "/mix-app/views/app-portal/pages/permission/components/parents/parents.html", - bindings: { - page: "=", - onDelete: "&", - onUpdate: "&", - }, -}); - app.component("postGeneral", { templateUrl: "/mix-app/views/app-portal/pages/post/components/general/view.html", @@ -8465,15 +8530,6 @@ app.component("postAdvanced", { ], }); -app.component("postSeo", { - templateUrl: "/mix-app/views/app-portal/pages/post/components/seo/view.html", - bindings: { - post: "=", - onDelete: "&", - onUpdate: "&", - }, -}); - app.component("postContent", { templateUrl: "/mix-app/views/app-portal/pages/post/components/post-content/view.html", @@ -8568,7 +8624,16 @@ app.component("postContent", { ], }); -modules.component("relatedPosts", { +app.component("postSeo", { + templateUrl: "/mix-app/views/app-portal/pages/post/components/seo/view.html", + bindings: { + post: "=", + onDelete: "&", + onUpdate: "&", + }, +}); + +modules.component("relatedPosts", { templateUrl: "/mix-app/views/app-portal/pages/post/components/related-navigations/view.html", bindings: { @@ -8774,163 +8839,6 @@ app.component("serviceMain", { }, }); -app.component("themeExportCultures", { - templateUrl: - "/mix-app/views/app-portal/pages/theme/components/theme-export-cultures/view.html", - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - function ($rootScope, $scope, ngAppSettings) { - var ctrl = this; - var service = $rootScope.getRestService("culture"); - ctrl.selectAllContent = false; - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.$onInit = async () => { - ctrl.getList(); - }; - ctrl.getList = async (cultureIndex) => { - if (cultureIndex !== undefined) { - ctrl.request.cultureIndex = cultureIndex; - } - if (ctrl.request.fromDate !== null) { - var d = new Date(ctrl.request.fromDate); - ctrl.request.fromDate = d.toISOString(); - } - if (ctrl.request.toDate !== null) { - var d = new Date(ctrl.request.toDate); - ctrl.request.toDate = d.toISOString(); - } - let getData = await service.getList(ctrl.request); - if (getData.success) { - ctrl.data = getData.data; - } - }; - ctrl.selectContent = (culture, selected) => { - ctrl.selectAllContent = ctrl.selectAllContent && selected; - ctrl.selectAllData = ctrl.selectAllData && selected; - culture.isExportData = selected && culture.isExportData; - ctrl.updateContent([culture.id], selected); - }; - ctrl.updateContent = function (arr, selected) { - if (selected) { - ctrl.exportThemeDto.cultureIds = ctrl.unionArray( - ctrl.exportThemeDto.cultureIds, - arr - ); - } else { - ctrl.exportThemeDto.cultureIds = - ctrl.exportThemeDto.cultureIds.filter((m) => arr.indexOf(m) < 0); - ctrl.updateData(arr, false); - } - }; - ctrl.selectAll = function (arr) { - // ctrl.selectedList.data = []; - var ids = arr.map(function (obj) { - return obj.id; - }); - ctrl.updateContent(ids, ctrl.selectAllContent); - angular.forEach(arr, function (e) { - e.isActived = ctrl.selectAllContent; - }); - }; - ctrl.unionArray = (a, b) => { - return [...new Set([...a, ...b])]; - }; - }, - ], - bindings: { - exportThemeDto: "=", - }, -}); - -app.component("themeExportMixDbTables", { - templateUrl: - "/mix-app/views/app-portal/pages/theme/components/theme-export-mix-db-tables/view.html", - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - "RestMixDbDatabaseService", - function ($rootScope, $scope, ngAppSettings, dbContextService) { - var ctrl = this; - var service = $rootScope.getRestService("mix-db-table"); - ctrl.selectAllContent = false; - ctrl.selectAllData = false; - ctrl.dbContextrequest = angular.copy(ngAppSettings.request); - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.$onInit = async () => { - ctrl.request.pageSize = null; - ctrl.loadDbContexts(); - }; - ctrl.loadDbContexts = async function (pageIndex) { - if (pageIndex !== undefined) { - ctrl.dbContextrequest.pageIndex = pageIndex; - } - - var resp = await dbContextService.getList(ctrl.dbContextrequest); - - if (resp && resp.success) { - ctrl.data = resp.data; - $scope.$apply(); - } - }; - - ctrl.selectContent = (mixDatabaseContext, selected) => { - ctrl.selectAllContent = ctrl.selectAllContent && selected; - ctrl.exportThemeDto.content.mixDbDatabaseIds = ctrl.updateArray( - ctrl.exportThemeDto.content.mixDbDatabaseIds, - [mixDatabaseContext.id], - selected - ); - }; - ctrl.selectDbContent = (mixDatabase, selected) => { - ctrl.selectAllContent = ctrl.selectAllContent && selected; - ctrl.selectAllData = ctrl.selectAllData && selected; - mixDatabase.isExportData = selected && mixDatabase.isExportData; - ctrl.exportThemeDto.content.mixDbTableIds = ctrl.updateArray( - ctrl.exportThemeDto.content.mixDbTableIds, - [mixDatabase.id], - selected - ); - if (!selected) { - ctrl.selectData(mixDatabase, false); - } - }; - ctrl.selectData = (mixDatabase, selected) => { - ctrl.selectAllData = ctrl.selectAllData && selected; - ctrl.exportThemeDto.associations.mixDbTableIds = ctrl.updateArray( - ctrl.exportThemeDto.associations.mixDbTableIds, - [mixDatabase.id], - selected - ); - }; - ctrl.updateArray = function (src, arr, selected) { - if (selected) { - src = ctrl.unionArray(src, arr); - } else { - src = src.filter((m) => arr.indexOf(m) < 0); - } - return src; - }; - - ctrl.selectAll = function (arr) { - angular.forEach(arr, function (e) { - ctrl.selectContent(e, ctrl.selectAllContent); - e.isActived = ctrl.selectAllContent; - e.isExportData = ctrl.selectAllData; - }); - }; - ctrl.unionArray = (a, b) => { - return [...new Set([...a, ...b])]; - }; - }, - ], - bindings: { - exportThemeDto: "=", - }, -}); - app.component("themeExportModules", { templateUrl: "/mix-app/views/app-portal/pages/theme/components/theme-export-modules/view.html", @@ -9028,74 +8936,64 @@ app.component("themeExportModules", { }, }); -app.component("themeExportPages", { +app.component("themeExportMixDbTables", { templateUrl: - "/mix-app/views/app-portal/pages/theme/components/theme-export-pages/view.html", + "/mix-app/views/app-portal/pages/theme/components/theme-export-mix-db-tables/view.html", controller: [ "$rootScope", "$scope", "ngAppSettings", - function ($rootScope, $scope, ngAppSettings) { + "RestMixDbDatabaseService", + function ($rootScope, $scope, ngAppSettings, dbContextService) { var ctrl = this; - var service = $rootScope.getRestService("mix-page"); + var service = $rootScope.getRestService("mix-db-table"); ctrl.selectAllContent = false; ctrl.selectAllData = false; + ctrl.dbContextrequest = angular.copy(ngAppSettings.request); ctrl.request = angular.copy(ngAppSettings.request); ctrl.$onInit = async () => { ctrl.request.pageSize = null; - ctrl.getList(); + ctrl.loadDbContexts(); }; - ctrl.getList = async (pageIndex) => { + ctrl.loadDbContexts = async function (pageIndex) { if (pageIndex !== undefined) { - ctrl.request.pageIndex = pageIndex; - } - if (ctrl.request.fromDate !== null) { - var d = new Date(ctrl.request.fromDate); - ctrl.request.fromDate = d.toISOString(); - } - if (ctrl.request.toDate !== null) { - var d = new Date(ctrl.request.toDate); - ctrl.request.toDate = d.toISOString(); + ctrl.dbContextrequest.pageIndex = pageIndex; } - let getData = await service.getList(ctrl.request); - if (getData.success) { - ctrl.data = getData.data; + + var resp = await dbContextService.getList(ctrl.dbContextrequest); + + if (resp && resp.success) { + ctrl.data = resp.data; + $scope.$apply(); } }; - ctrl.selectContent = (page, selected) => { + + ctrl.selectContent = (mixDatabaseContext, selected) => { ctrl.selectAllContent = ctrl.selectAllContent && selected; - ctrl.selectAllData = ctrl.selectAllData && selected; - page.isExportData = selected && page.isExportData; - let contentIds = page.contents.map(function (obj) { - return obj.id; - }); - ctrl.exportThemeDto.content.pageIds = ctrl.updateArray( - ctrl.exportThemeDto.content.pageIds, - [page.id], + ctrl.exportThemeDto.content.mixDbDatabaseIds = ctrl.updateArray( + ctrl.exportThemeDto.content.mixDbDatabaseIds, + [mixDatabaseContext.id], selected ); - ctrl.exportThemeDto.content.pageContentIds = ctrl.updateArray( - ctrl.exportThemeDto.content.pageContentIds, - contentIds, + }; + ctrl.selectDbContent = (mixDatabase, selected) => { + ctrl.selectAllContent = ctrl.selectAllContent && selected; + ctrl.selectAllData = ctrl.selectAllData && selected; + mixDatabase.isExportData = selected && mixDatabase.isExportData; + ctrl.exportThemeDto.content.mixDbTableIds = ctrl.updateArray( + ctrl.exportThemeDto.content.mixDbTableIds, + [mixDatabase.id], selected ); if (!selected) { - ctrl.selectData(page, false); + ctrl.selectData(mixDatabase, false); } }; - ctrl.selectData = (page, selected) => { + ctrl.selectData = (mixDatabase, selected) => { ctrl.selectAllData = ctrl.selectAllData && selected; - let contentIds = page.contents.map(function (obj) { - return obj.id; - }); - ctrl.exportThemeDto.associations.pageIds = ctrl.updateArray( - ctrl.exportThemeDto.associations.pageIds, - [page.id], - selected - ); - ctrl.exportThemeDto.associations.pageContentIds = ctrl.updateArray( - ctrl.exportThemeDto.associations.pageContentIds, - contentIds, + ctrl.exportThemeDto.associations.mixDbTableIds = ctrl.updateArray( + ctrl.exportThemeDto.associations.mixDbTableIds, + [mixDatabase.id], selected ); }; @@ -9107,10 +9005,10 @@ app.component("themeExportPages", { } return src; }; + ctrl.selectAll = function (arr) { angular.forEach(arr, function (e) { ctrl.selectContent(e, ctrl.selectAllContent); - ctrl.selectData(e, ctrl.selectAllData); e.isActived = ctrl.selectAllContent; e.isExportData = ctrl.selectAllData; }); @@ -9125,20 +9023,187 @@ app.component("themeExportPages", { }, }); -app.component("themeExportPosts", { +app.component("themeExportCultures", { templateUrl: - "/mix-app/views/app-portal/pages/theme/components/theme-export-posts/view.html", + "/mix-app/views/app-portal/pages/theme/components/theme-export-cultures/view.html", controller: [ "$rootScope", "$scope", "ngAppSettings", - "BaseRestService", - function ($rootScope, $scope, ngAppSettings, baseRestService) { + function ($rootScope, $scope, ngAppSettings) { var ctrl = this; - var service = angular.copy(baseRestService); - service.initService("/rest/mix-portal", "mix-post"); + var service = $rootScope.getRestService("culture"); ctrl.selectAllContent = false; - ctrl.selectAllData = false; + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.$onInit = async () => { + ctrl.getList(); + }; + ctrl.getList = async (cultureIndex) => { + if (cultureIndex !== undefined) { + ctrl.request.cultureIndex = cultureIndex; + } + if (ctrl.request.fromDate !== null) { + var d = new Date(ctrl.request.fromDate); + ctrl.request.fromDate = d.toISOString(); + } + if (ctrl.request.toDate !== null) { + var d = new Date(ctrl.request.toDate); + ctrl.request.toDate = d.toISOString(); + } + let getData = await service.getList(ctrl.request); + if (getData.success) { + ctrl.data = getData.data; + } + }; + ctrl.selectContent = (culture, selected) => { + ctrl.selectAllContent = ctrl.selectAllContent && selected; + ctrl.selectAllData = ctrl.selectAllData && selected; + culture.isExportData = selected && culture.isExportData; + ctrl.updateContent([culture.id], selected); + }; + ctrl.updateContent = function (arr, selected) { + if (selected) { + ctrl.exportThemeDto.cultureIds = ctrl.unionArray( + ctrl.exportThemeDto.cultureIds, + arr + ); + } else { + ctrl.exportThemeDto.cultureIds = + ctrl.exportThemeDto.cultureIds.filter((m) => arr.indexOf(m) < 0); + ctrl.updateData(arr, false); + } + }; + ctrl.selectAll = function (arr) { + // ctrl.selectedList.data = []; + var ids = arr.map(function (obj) { + return obj.id; + }); + ctrl.updateContent(ids, ctrl.selectAllContent); + angular.forEach(arr, function (e) { + e.isActived = ctrl.selectAllContent; + }); + }; + ctrl.unionArray = (a, b) => { + return [...new Set([...a, ...b])]; + }; + }, + ], + bindings: { + exportThemeDto: "=", + }, +}); + +app.component("themeExportPages", { + templateUrl: + "/mix-app/views/app-portal/pages/theme/components/theme-export-pages/view.html", + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + function ($rootScope, $scope, ngAppSettings) { + var ctrl = this; + var service = $rootScope.getRestService("mix-page"); + ctrl.selectAllContent = false; + ctrl.selectAllData = false; + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.$onInit = async () => { + ctrl.request.pageSize = null; + ctrl.getList(); + }; + ctrl.getList = async (pageIndex) => { + if (pageIndex !== undefined) { + ctrl.request.pageIndex = pageIndex; + } + if (ctrl.request.fromDate !== null) { + var d = new Date(ctrl.request.fromDate); + ctrl.request.fromDate = d.toISOString(); + } + if (ctrl.request.toDate !== null) { + var d = new Date(ctrl.request.toDate); + ctrl.request.toDate = d.toISOString(); + } + let getData = await service.getList(ctrl.request); + if (getData.success) { + ctrl.data = getData.data; + } + }; + ctrl.selectContent = (page, selected) => { + ctrl.selectAllContent = ctrl.selectAllContent && selected; + ctrl.selectAllData = ctrl.selectAllData && selected; + page.isExportData = selected && page.isExportData; + let contentIds = page.contents.map(function (obj) { + return obj.id; + }); + ctrl.exportThemeDto.content.pageIds = ctrl.updateArray( + ctrl.exportThemeDto.content.pageIds, + [page.id], + selected + ); + ctrl.exportThemeDto.content.pageContentIds = ctrl.updateArray( + ctrl.exportThemeDto.content.pageContentIds, + contentIds, + selected + ); + if (!selected) { + ctrl.selectData(page, false); + } + }; + ctrl.selectData = (page, selected) => { + ctrl.selectAllData = ctrl.selectAllData && selected; + let contentIds = page.contents.map(function (obj) { + return obj.id; + }); + ctrl.exportThemeDto.associations.pageIds = ctrl.updateArray( + ctrl.exportThemeDto.associations.pageIds, + [page.id], + selected + ); + ctrl.exportThemeDto.associations.pageContentIds = ctrl.updateArray( + ctrl.exportThemeDto.associations.pageContentIds, + contentIds, + selected + ); + }; + ctrl.updateArray = function (src, arr, selected) { + if (selected) { + src = ctrl.unionArray(src, arr); + } else { + src = src.filter((m) => arr.indexOf(m) < 0); + } + return src; + }; + ctrl.selectAll = function (arr) { + angular.forEach(arr, function (e) { + ctrl.selectContent(e, ctrl.selectAllContent); + ctrl.selectData(e, ctrl.selectAllData); + e.isActived = ctrl.selectAllContent; + e.isExportData = ctrl.selectAllData; + }); + }; + ctrl.unionArray = (a, b) => { + return [...new Set([...a, ...b])]; + }; + }, + ], + bindings: { + exportThemeDto: "=", + }, +}); + +app.component("themeExportPosts", { + templateUrl: + "/mix-app/views/app-portal/pages/theme/components/theme-export-posts/view.html", + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "BaseRestService", + function ($rootScope, $scope, ngAppSettings, baseRestService) { + var ctrl = this; + var service = angular.copy(baseRestService); + service.initService("/rest/mix-portal", "mix-post"); + ctrl.selectAllContent = false; + ctrl.selectAllData = false; ctrl.request = angular.copy(ngAppSettings.request); ctrl.$onInit = async () => { ctrl.request.pageSize = 1000; @@ -9294,88 +9359,6 @@ app.component("themeImportCultures", { }, }); -app.component("themeImportMixDbTables", { - templateUrl: - "/mix-app/views/app-portal/pages/theme-import/components/theme-import-mix-db-tables/view.html", - bindings: { - importData: "=", - importThemeDto: "=", - }, - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - function ($rootScope, $scope, ngAppSettings) { - var ctrl = this; - var service = $rootScope.getRestService("mix-db-table"); - ctrl.selectAllContent = false; - ctrl.selectAllData = false; - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.$onInit = async () => { - ctrl.data = ctrl.importData.mixDbTables; - }; - - ctrl.selectContent = (mixDatabase, selected) => { - ctrl.selectAllContent = ctrl.selectAllContent && selected; - ctrl.selectAllData = ctrl.selectAllData && selected; - mixDatabase.isImportData = selected && mixDatabase.isImportData; - ctrl.importThemeDto.mixDbTableIds = ctrl.updateArray( - ctrl.importThemeDto.mixDbTableIds, - [mixDatabase.id], - selected - ); - if (!selected) { - ctrl.selectData(mixDatabase, false); - } - }; - ctrl.selectData = (mixDatabase, selected) => { - ctrl.selectAllData = ctrl.selectAllData && selected; - ctrl.importThemeDto.mixDbDataIds = ctrl.updateArray( - ctrl.importThemeDto.mixDbDataIds, - [mixDatabase.id], - selected - ); - }; - ctrl.updateArray = function (src, arr, selected) { - if (selected) { - src = ctrl.unionArray(src, arr); - } else { - src = src.filter((m) => arr.indexOf(m) < 0); - } - return src; - }; - ctrl.selectAll = function (arr) { - angular.forEach(arr, function (e) { - ctrl.selectContent(e, ctrl.selectAllContent); - ctrl.selectData(e, ctrl.selectAllData); - e.isActived = ctrl.selectAllContent; - e.isImportData = ctrl.selectAllData; - }); - }; - ctrl.checkExist = (mixDatabase) => { - return ctrl.importData.existingDatabases.find( - (m) => m.id == mixDatabase.id - ); - }; - ctrl.unionArray = (a, b) => { - return [...new Set([...a, ...b])]; - }; - ctrl.colClass = (kind) => { - switch (kind) { - case "New": - return "fa fa-plus text-success"; - case "Changed": - return "fa fa-pencil text-warning"; - case "Deleted": - return "fa fa-minus text-danger"; - default: - break; - } - }; - }, - ], -}); - app.component("themeImportModules", { templateUrl: "/mix-app/views/app-portal/pages/theme-import/components/theme-import-modules/view.html", @@ -9472,10 +9455,92 @@ app.component("themeImportModules", { }, }); -app.component("themeImportPages", { +app.component("themeImportMixDbTables", { templateUrl: - "/mix-app/views/app-portal/pages/theme-import/components/theme-import-pages/view.html", - controller: [ + "/mix-app/views/app-portal/pages/theme-import/components/theme-import-mix-db-tables/view.html", + bindings: { + importData: "=", + importThemeDto: "=", + }, + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + function ($rootScope, $scope, ngAppSettings) { + var ctrl = this; + var service = $rootScope.getRestService("mix-db-table"); + ctrl.selectAllContent = false; + ctrl.selectAllData = false; + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.$onInit = async () => { + ctrl.data = ctrl.importData.mixDbTables; + }; + + ctrl.selectContent = (mixDatabase, selected) => { + ctrl.selectAllContent = ctrl.selectAllContent && selected; + ctrl.selectAllData = ctrl.selectAllData && selected; + mixDatabase.isImportData = selected && mixDatabase.isImportData; + ctrl.importThemeDto.mixDbTableIds = ctrl.updateArray( + ctrl.importThemeDto.mixDbTableIds, + [mixDatabase.id], + selected + ); + if (!selected) { + ctrl.selectData(mixDatabase, false); + } + }; + ctrl.selectData = (mixDatabase, selected) => { + ctrl.selectAllData = ctrl.selectAllData && selected; + ctrl.importThemeDto.mixDbDataIds = ctrl.updateArray( + ctrl.importThemeDto.mixDbDataIds, + [mixDatabase.id], + selected + ); + }; + ctrl.updateArray = function (src, arr, selected) { + if (selected) { + src = ctrl.unionArray(src, arr); + } else { + src = src.filter((m) => arr.indexOf(m) < 0); + } + return src; + }; + ctrl.selectAll = function (arr) { + angular.forEach(arr, function (e) { + ctrl.selectContent(e, ctrl.selectAllContent); + ctrl.selectData(e, ctrl.selectAllData); + e.isActived = ctrl.selectAllContent; + e.isImportData = ctrl.selectAllData; + }); + }; + ctrl.checkExist = (mixDatabase) => { + return ctrl.importData.existingDatabases.find( + (m) => m.id == mixDatabase.id + ); + }; + ctrl.unionArray = (a, b) => { + return [...new Set([...a, ...b])]; + }; + ctrl.colClass = (kind) => { + switch (kind) { + case "New": + return "fa fa-plus text-success"; + case "Changed": + return "fa fa-pencil text-warning"; + case "Deleted": + return "fa fa-minus text-danger"; + default: + break; + } + }; + }, + ], +}); + +app.component("themeImportPages", { + templateUrl: + "/mix-app/views/app-portal/pages/theme-import/components/theme-import-pages/view.html", + controller: [ "$rootScope", "$scope", "ngAppSettings", @@ -9970,6 +10035,176 @@ modules.component("actions", { ], }); +modules.component("additionalValue", { + templateUrl: + "/mix-app/views/app-portal/components/additional-value/view.html", + bindings: { + additionalData: "=?", + additionalDataId: "=?", + parentType: "=?", + parentId: "=?", + mixDbTableName: "=?", + backUrl: "=?", + }, + controller: [ + "$rootScope", + "$scope", + "RestMixDbDataPortalService", + function ($rootScope, $scope, dataService) { + var ctrl = this; + ctrl.value = {}; + ctrl.column = { dataType: "Text" }; + ctrl.selectedCol = null; + ctrl.mixConfigurations = $rootScope.globalSettings; + ctrl.$onInit = async function () { + if (!ctrl.additionalData) { + if (!ctrl.additionalDataId) { + const obj = { + parentType: ctrl.parentType, + parentId: ctrl.parentId, + databaseName: ctrl.mixDbTableName, + }; + const getData = await dataService.getAdditionalData(obj); + if (getData.success) { + ctrl.additionalData = getData.data; + ctrl.additionalData.mixDbTableName = ctrl.mixDbTableName; + ctrl.additionalData.parentType = ctrl.parentType; + $scope.$apply(); + } else { + $rootScope.showErrors(getData.errors); + } + } else { + var getData = await dataService.getSingle([ctrl.additionalDataId]); + ctrl.additionalData = getData.data; + $scope.$apply(); + } + } + if (ctrl.additionalData.id == "00000000-0000-0000-0000-000000000000") { + ctrl.additionalData.id = null; + } + }; + }, + ], +}); + +modules.component("additionalColumn", { + templateUrl: + "/mix-app/views/app-portal/components/additional-column/view.html", + bindings: { + model: "=", + additionalData: "=", + }, + controller: [ + "$rootScope", + "$scope", + "RestMixDbColumnPortalService", + "RestMixDbDataPortalService", + function ($rootScope, $scope, columnService, dataService) { + var ctrl = this; + ctrl.value = {}; + ctrl.column = { + dataType: "Text", + mixDbTableName: "sysAdditionalColumn", + mixDbTableId: 6, + status: "Published", + }; + ctrl.selectedCol = null; + ctrl.mixConfigurations = $rootScope.globalSettings; + ctrl.$onInit = async function () {}; + ctrl.addAttr = async function () { + if (ctrl.column.name) { + var current = $rootScope.findObjectByKey( + ctrl.additionalData.columns, + "name", + ctrl.column.name + ); + if (current) { + $rootScope.showErrors(["Field " + ctrl.column.name + " existed!"]); + } else { + ctrl.column.priority = ctrl.additionalData.columns.length + 1; + $rootScope.isBusy = true; + var saveField = await columnService.create(ctrl.column); + $rootScope.isBusy = false; + if (saveField.success) { + ctrl.additionalData.columns.push(saveField.data); + if (ctrl.additionalData.parentId) { + await dataService.save(ctrl.additionalData); + } + //reset column option + ctrl.column.title = ""; + ctrl.column.name = ""; + ctrl.column.dataType = "Text"; + } else { + $rootScope.showErrors(saveField.errors); + } + $scope.$apply(); + } + } else { + $rootScope.showErrors(["Please add column Name"]); + } + }; + + ctrl.generateName = function (col) { + col.name = $rootScope.generateKeyword(col.title, "_", true, true); + }; + ctrl.showReferences = function (col) { + ctrl.colRef = col; + $("#modal-navs").modal("show"); + }; + ctrl.referenceCallback = async function (selected) { + if (selected && selected.length) { + ctrl.colRef.reference = selected; + ctrl.colRef.referenceId = selected[0].id; + await columnService.save(ctrl.colRef); + } + $("#modal-navs").modal("hide"); + }; + ctrl.updateOrders = function (index) { + if (index > ctrl.dragStartIndex) { + ctrl.additionalData.columns.splice(ctrl.dragStartIndex, 1); + } else { + ctrl.additionalData.columns.splice(ctrl.dragStartIndex + 1, 1); + } + angular.forEach(ctrl.additionalData.columns, function (e, i) { + e.priority = i; + }); + }; + + ctrl.dragStart = function (index) { + ctrl.dragStartIndex = index; + }; + + ctrl.removeAttribute = function (val, index) { + $rootScope.showConfirm( + ctrl, + "removeAttributeConfirmed", + [val, index], + null, + "Remove Field", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + ctrl.removeAttributeConfirmed = async function (val, index) { + if (val.id) { + $rootScope.isBusy = true; + var result = await columnService.delete([val.id]); + if (result.success) { + ctrl.additionalData.columns.splice(index, 1); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(result.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + } else { + ctrl.additionalData.columns.splice(index, 1); + } + }; + }, + ], +}); + modules.component("layoutPortalSidebar", { templateUrl: "/mix-app/views/app-portal/components/_layout-portal-sidebar/view.html", @@ -10284,258 +10519,7 @@ modules.component("customImage", { ], }); -modules.component("additionalValue", { - templateUrl: - "/mix-app/views/app-portal/components/additional-value/view.html", - bindings: { - additionalData: "=?", - additionalDataId: "=?", - parentType: "=?", - parentId: "=?", - mixDbTableName: "=?", - backUrl: "=?", - }, - controller: [ - "$rootScope", - "$scope", - "RestMixDbDataPortalService", - function ($rootScope, $scope, dataService) { - var ctrl = this; - ctrl.value = {}; - ctrl.column = { dataType: "Text" }; - ctrl.selectedCol = null; - ctrl.mixConfigurations = $rootScope.globalSettings; - ctrl.$onInit = async function () { - if (!ctrl.additionalData) { - if (!ctrl.additionalDataId) { - const obj = { - parentType: ctrl.parentType, - parentId: ctrl.parentId, - databaseName: ctrl.mixDbTableName, - }; - const getData = await dataService.getAdditionalData(obj); - if (getData.success) { - ctrl.additionalData = getData.data; - ctrl.additionalData.mixDbTableName = ctrl.mixDbTableName; - ctrl.additionalData.parentType = ctrl.parentType; - $scope.$apply(); - } else { - $rootScope.showErrors(getData.errors); - } - } else { - var getData = await dataService.getSingle([ctrl.additionalDataId]); - ctrl.additionalData = getData.data; - $scope.$apply(); - } - } - if (ctrl.additionalData.id == "00000000-0000-0000-0000-000000000000") { - ctrl.additionalData.id = null; - } - }; - }, - ], -}); - -modules.component("funding", { - templateUrl: "/mix-app/views/app-portal/components/funding/view.html", - controller: [ - "$rootScope", - "$http", - function ($rootScope, $http) { - var ctrl = this; - ctrl.items = [ - { - title: "opencollective.com/mixcore", - href: "https://opencollective.com/mixcore", - logo: - "https://github.githubassets.com/images/modules/site/icons/funding_platforms/open_collective.svg", - }, - { - title: "funding.communitybridge.org/projects/mixcore", - href: "https://crowdfunding.lfx.linuxfoundation.org/projects/mixcore", - logo: - "https://github.githubassets.com/images/modules/site/icons/funding_platforms/community_bridge.svg", - }, - { - title: "patreon.com/mixcore", - href: "https://www.patreon.com/mixcore/creators", - logo: - "https://github.githubassets.com/images/modules/site/icons/funding_platforms/patreon.svg", - }, - { - title: "paypalme/mixcore", - href: "https://www.paypal.me/mixcore", - logo: "/mix-app/assets/img/svg/heart.svg", - }, - { - title: "buymeacoffee.com/mixcore", - href: "https://www.buymeacoffee.com/mixcore", - logo: "/mix-app/assets/img/svg/heart.svg", - }, - ]; - ctrl.init = function () {}; - }, - ], - bindings: {}, -}); - -modules.component("additionalColumn", { - templateUrl: - "/mix-app/views/app-portal/components/additional-column/view.html", - bindings: { - model: "=", - additionalData: "=", - }, - controller: [ - "$rootScope", - "$scope", - "RestMixDbColumnPortalService", - "RestMixDbDataPortalService", - function ($rootScope, $scope, columnService, dataService) { - var ctrl = this; - ctrl.value = {}; - ctrl.column = { - dataType: "Text", - mixDbTableName: "sysAdditionalColumn", - mixDbTableId: 6, - status: "Published", - }; - ctrl.selectedCol = null; - ctrl.mixConfigurations = $rootScope.globalSettings; - ctrl.$onInit = async function () {}; - ctrl.addAttr = async function () { - if (ctrl.column.name) { - var current = $rootScope.findObjectByKey( - ctrl.additionalData.columns, - "name", - ctrl.column.name - ); - if (current) { - $rootScope.showErrors(["Field " + ctrl.column.name + " existed!"]); - } else { - ctrl.column.priority = ctrl.additionalData.columns.length + 1; - $rootScope.isBusy = true; - var saveField = await columnService.create(ctrl.column); - $rootScope.isBusy = false; - if (saveField.success) { - ctrl.additionalData.columns.push(saveField.data); - if (ctrl.additionalData.parentId) { - await dataService.save(ctrl.additionalData); - } - //reset column option - ctrl.column.title = ""; - ctrl.column.name = ""; - ctrl.column.dataType = "Text"; - } else { - $rootScope.showErrors(saveField.errors); - } - $scope.$apply(); - } - } else { - $rootScope.showErrors(["Please add column Name"]); - } - }; - - ctrl.generateName = function (col) { - col.name = $rootScope.generateKeyword(col.title, "_", true, true); - }; - ctrl.showReferences = function (col) { - ctrl.colRef = col; - $("#modal-navs").modal("show"); - }; - ctrl.referenceCallback = async function (selected) { - if (selected && selected.length) { - ctrl.colRef.reference = selected; - ctrl.colRef.referenceId = selected[0].id; - await columnService.save(ctrl.colRef); - } - $("#modal-navs").modal("hide"); - }; - ctrl.updateOrders = function (index) { - if (index > ctrl.dragStartIndex) { - ctrl.additionalData.columns.splice(ctrl.dragStartIndex, 1); - } else { - ctrl.additionalData.columns.splice(ctrl.dragStartIndex + 1, 1); - } - angular.forEach(ctrl.additionalData.columns, function (e, i) { - e.priority = i; - }); - }; - - ctrl.dragStart = function (index) { - ctrl.dragStartIndex = index; - }; - - ctrl.removeAttribute = function (val, index) { - $rootScope.showConfirm( - ctrl, - "removeAttributeConfirmed", - [val, index], - null, - "Remove Field", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); - }; - ctrl.removeAttributeConfirmed = async function (val, index) { - if (val.id) { - $rootScope.isBusy = true; - var result = await columnService.delete([val.id]); - if (result.success) { - ctrl.additionalData.columns.splice(index, 1); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(result.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - } else { - ctrl.additionalData.columns.splice(index, 1); - } - }; - }, - ], -}); - -modules.component("githubContributers", { - templateUrl: - "/mix-app/views/app-portal/components/github-contributers/view.html", - controller: [ - "$rootScope", - "$http", - function ($rootScope, $http) { - var ctrl = this; - ctrl.items = []; - ctrl.init = function () { - var req = { - method: "GET", - url: "https://api.github.com/repos/mixcore/mix.core/contributors", - }; - ctrl.getGithubApiResult(req); - }; - - ctrl.getGithubApiResult = async function (req) { - return $http(req).then( - function (resp) { - if (resp.status == "200") { - ctrl.items = resp.data; - } else { - } - }, - function (error) { - return { - success: false, - errors: [error.statusText || error.status], - }; - } - ); - }; - }, - ], - bindings: {}, -}); - -modules.component("filterList", { +modules.component("filterList", { templateUrl: "/mix-app/views/app-portal/components/filter-list/filter-list.html", controller: [ @@ -10609,8 +10593,9 @@ modules.component("filterList", { }, }); -modules.component("githubReleases", { - templateUrl: "/mix-app/views/app-portal/components/github-releases/view.html", +modules.component("githubContributers", { + templateUrl: + "/mix-app/views/app-portal/components/github-contributers/view.html", controller: [ "$rootScope", "$http", @@ -10620,7 +10605,7 @@ modules.component("githubReleases", { ctrl.init = function () { var req = { method: "GET", - url: "https://api.github.com/repos/mixcore/mix.core/releases", + url: "https://api.github.com/repos/mixcore/mix.core/contributors", }; ctrl.getGithubApiResult(req); }; @@ -10646,296 +10631,85 @@ modules.component("githubReleases", { bindings: {}, }); -modules.component("jsonBuilder", { - templateUrl: "/mix-app/views/app-portal/components/json-builder/view.html", - bindings: { - data: "=?", // json obj (ex: { column1: 'some val' }) - strData: "=?", // json obj (ex: { column1: 'some val' }) - folder: "=?", // filepath (ex: 'data/jsonfile.json') - filename: "=?", // filepath (ex: 'data/jsonfile.json') - allowedTypes: "=?", // string array ( ex: [ 'type1', 'type2' ] ) - backUrl: "=?", // string array ( ex: [ 'type1', 'type2' ] ) - showPreview: "=?", - type: "=?", // array / obj - editMode: "=?", // array / obj - save: "&", - onUpdate: "&", - }, +modules.component("githubReleases", { + templateUrl: "/mix-app/views/app-portal/components/github-releases/view.html", controller: [ "$rootScope", - "$scope", - "$location", - "FileServices", - "ngAppSettings", - function ($rootScope, $scope, $location, fileService, ngAppSettings) { + "$http", + function ($rootScope, $http) { var ctrl = this; + ctrl.items = []; + ctrl.init = function () { + var req = { + method: "GET", + url: "https://api.github.com/repos/mixcore/mix.core/releases", + }; + ctrl.getGithubApiResult(req); + }; - ctrl.file = null; - ctrl.translate = $rootScope.translate; - ctrl.mixConfigurations = $rootScope.globalSettings; - ctrl.timestamp = Math.random(); - ctrl.templates = [ + ctrl.getGithubApiResult = async function (req) { + return $http(req).then( + function (resp) { + if (resp.status == "200") { + ctrl.items = resp.data; + } else { + } + }, + function (error) { + return { + success: false, + errors: [error.statusText || error.status], + }; + } + ); + }; + }, + ], + bindings: {}, +}); + +modules.component("funding", { + templateUrl: "/mix-app/views/app-portal/components/funding/view.html", + controller: [ + "$rootScope", + "$http", + function ($rootScope, $http) { + var ctrl = this; + ctrl.items = [ { - type: "item", - name: "", - dataType: "Text", - value: "", - columns: [{ allowedTypes: ["item"], items: [] }], + title: "opencollective.com/mixcore", + href: "https://opencollective.com/mixcore", + logo: + "https://github.githubassets.com/images/modules/site/icons/funding_platforms/open_collective.svg", }, { - type: "string", - dataType: "Text", - value: "", - columns: [{ allowedTypes: ["item"], items: [] }], + title: "funding.communitybridge.org/projects/mixcore", + href: "https://crowdfunding.lfx.linuxfoundation.org/projects/mixcore", + logo: + "https://github.githubassets.com/images/modules/site/icons/funding_platforms/community_bridge.svg", }, { - type: "object", - name: "o1", - columns: [{ allowedTypes: ["array", "object", "item"], items: [] }], + title: "patreon.com/mixcore", + href: "https://www.patreon.com/mixcore/creators", + logo: + "https://github.githubassets.com/images/modules/site/icons/funding_platforms/patreon.svg", }, { - type: "array", - name: "a1", - columns: [{ allowedTypes: ["object"], items: [] }], + title: "paypalme/mixcore", + href: "https://www.paypal.me/mixcore", + logo: "/mix-app/assets/img/svg/heart.svg", + }, + { + title: "buymeacoffee.com/mixcore", + href: "https://www.buymeacoffee.com/mixcore", + logo: "/mix-app/assets/img/svg/heart.svg", }, ]; - ctrl.draft = []; - ctrl.model = {}; - ctrl.dropzones = { - root: [], - }; - ctrl.selected = null; - ctrl.selectedModel = {}; - ctrl.strModel = null; - ctrl.init = async function () { - var arr = []; - if (!ctrl.editMode) { - ctrl.editMode = "json"; - } - if (!ctrl.data && ctrl.filename) { - await ctrl.loadFile(); - ctrl.parseObjToList(ctrl.data, arr); - ctrl.dropzones.root = arr; - } else { - if (!ctrl.data) { - if (ctrl.strData) { - ctrl.data = JSON.parse(ctrl.strData); - } - if (!ctrl.data && ctrl.type) { - ctrl.data = ctrl.type == "array" ? [] : {}; - } - } - ctrl.rootType = Array.isArray(ctrl.data) ? "array" : "object"; - ctrl.parseObjToList(ctrl.data, arr); - ctrl.strData = JSON.stringify(ctrl.data); - ctrl.dropzones.root = arr; - ctrl.preview = angular.copy(ctrl.data); - } - }; - ctrl.loadFile = async function () { - $rootScope.isBusy = true; - $scope.listUrl = "/admin/json-data/list?folder=" + ctrl.folder; - - var response = await fileService.getFile(ctrl.folder, ctrl.filename); - if (response.success) { - ctrl.file = response.data; - ctrl.data = JSON.parse(response.data.content); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - ctrl.saveFile = async function () { - $rootScope.isBusy = true; - ctrl.model = {}; - ctrl.update(); - if (ctrl.save) { - ctrl.save({ data: ctrl.model }); - } else { - // ctrl.parseObj(ctrl.dropzones.root, ctrl.model); - ctrl.file.content = JSON.stringify(ctrl.model); - var resp = await fileService.saveFile(ctrl.file); - if (resp && resp.success) { - $scope.activedFile = resp.data; - $rootScope.showMessage("Update successfully!", "success"); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - } - ctrl.select(ctrl.selected); - }; - ctrl.update = function () { - ctrl.model = {}; - var obj = { - type: "object", - name: "data", - columns: [ - { - items: ctrl.dropzones.root, - }, - ], - }; - ctrl.parseObj(obj, ctrl.model); - ctrl.strData = JSON.stringify(ctrl.model); - ctrl.onUpdate({ data: ctrl.model }); - }; - ctrl.updateJsonContent = function (strData) { - if (strData) { - ctrl.model = JSON.parse(strData); - ctrl.strData = strData; - ctrl.onUpdate({ data: ctrl.model }); - } - }; - ctrl.parseObjToList = function (item, items) { - // key: the name of the object key - // index: the ordinal position of the key within the object - if (Array.isArray(item)) { - angular.forEach(item, (e) => { - var obj = angular.copy(ctrl.templates[1]); - obj.value = e; - // ctrl.parseObjToList(e, obj.columns[0].items); - items.push(obj); - }); - } else { - Object.keys(item).forEach(function (key) { - var obj = {}; - if (item[key]) { - var objType = typeof item[key]; - switch (objType) { - case "object": - if (Array.isArray(item[key])) { - obj = angular.copy(ctrl.templates[2]); - obj.name = key; - ctrl.parseObjToList(item[key], obj.columns[0].items); - items.push(obj); - } else { - obj = angular.copy(ctrl.templates[1]); - obj.name = key; - ctrl.parseObjToList(item[key], obj.columns[0].items); - items.push(obj); - } - break; - default: - obj = angular.copy(ctrl.templates[0]); - obj.name = key; - obj.value = item[key]; - items.push(obj); - break; - } - } - }); - } - }; - ctrl.parseObj = function (item, obj, name) { - switch (item.type) { - case "array": - obj[item.name] = []; - angular.forEach(item.columns[0].items, (sub) => { - var o = {}; - ctrl.parseObj(sub, o); - obj[item.name].push(o); - }); - break; - case "object": - angular.forEach(item.columns[0].items, (sub) => { - if (sub.type == "object") { - var o = {}; - ctrl.parseObj(sub, o); - obj[item.name] = o; - } else { - ctrl.parseObj(sub, obj, item.name); - } - }); - break; - case "item": - obj[item.name] = item.value; - break; - } - }; - ctrl.parseJsonObject = function () { - if (ctrl.rootType == "object") { - ctrl.data = {}; - angular.forEach(ctrl.dropzones.root, (sub) => { - if (sub.type == "object") { - var o = {}; - ctrl.parseObj(sub, o); - ctrl.data[sub.name] = o; - } else { - ctrl.data[sub.name] = sub.value; - } - }); - } else { - ctrl.data = []; - if (ctrl.rootType == "array") { - angular.forEach(ctrl.dropzones.root, (sub) => { - ctrl.data.push(sub.value); - }); - } - } - ctrl.strData = JSON.stringify(ctrl.data); - ctrl.onUpdate({ data: JSON.stringify(ctrl.data) }); - }; - ctrl.select = function (item) { - if (ctrl.selected == item) { - ctrl.parseObj(item, ctrl.selectedModel); - } else { - ctrl.selected = item; - ctrl.selectedModel = {}; - ctrl.parseObj(item, ctrl.selectedModel); - } - ctrl.timestamp = Math.random(); - }; - ctrl.addField = function () { - var column = angular.copy(ctrl.templates[0]); - ctrl.dropzones.root.push(column); - ctrl.parseJsonObject(); - }; - ctrl.addString = function () { - var column = angular.copy(ctrl.templates[1]); - ctrl.dropzones.root.push(column); - ctrl.parseJsonObject(); - }; - ctrl.addObj = function (item) { - var obj = angular.copy(ctrl.templates[1]); - obj.name = "o" + (item.columns[0].items.length + 1); - item.columns[0].items.push(obj); - item.showMenu = false; - ctrl.parseJsonObject(); - }; - ctrl.addArray = function (item) { - var obj = angular.copy(ctrl.templates[2]); - obj.name = "a" + (item.columns[0].items.length + 1); - item.columns[0].items.push(obj); - item.showMenu = false; - ctrl.parseJsonObject(); - }; - ctrl.clone = function (item, list) { - var obj = angular.copy(item); - obj.name = item.name + "_copy"; - item.showMenu = false; - obj.showMenu = false; - list.items.push(obj); - ctrl.parseJsonObject(); - }; - - ctrl.remove = function (index, list) { - if (confirm("Remove this")) { - list.splice(index, 1); - ctrl.parseJsonObject(); - } - }; - }, - ], -}); + ctrl.init = function () {}; + }, + ], + bindings: {}, +}); modules.component("googleAnalytic", { templateUrl: "/mix-app/views/app-portal/components/google-analytic/view.html", @@ -11143,110 +10917,6 @@ modules.component("googleAnalytic", { ], }); -(function (angular) { - app.component("headerNav", { - templateUrl: - "/mix-app/views/app-portal/components/header-nav/headerNav.html", - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - "localStorageService", - "CommonService", - "ApiService", - "AuthService", - "CultureService", - function ( - $rootScope, - $scope, - ngAppSettings, - localStorageService, - commonService, - apiService, - authService, - cultureService - ) { - var ctrl = this; - ctrl.appSettings = $rootScope.globalSettings; - ctrl.isInRole = $rootScope.isInRole; - this.$onInit = function () { - ctrl.isAdmin = $rootScope.isAdmin; - ctrl.mixConfigurations = $rootScope.mixConfigurations; - cultureService.getList(ngAppSettings.request).then((resp) => { - ctrl.cultures = resp.data.items; - ctrl.selectedCulture = ctrl.cultures.find( - (m) => - m.specificulture == $rootScope.globalSettings.defaultCulture - ); - $scope.$apply(); - }); - authService.fillAuthData().then(() => { - if ( - authService.authentication && - authService.authentication.info.userData - ) { - ctrl.avatar = authService.authentication.info.userData.avatar; - } - }); - }; - ctrl.translate = $rootScope.translate; - ctrl.getConfiguration = function (keyword, isWrap, defaultText) { - return $rootScope.getConfiguration(keyword, isWrap, defaultText); - }; - ctrl.changeLang = function (culture) { - $rootScope.globalSettings.defaultCulture = culture.specificulture; - localStorageService.set("globalSettings", $rootScope.globalSettings); - window.top.location = location.href; - }; - ctrl.logOut = function () { - $rootScope.logOut(); - }; - ctrl.addPermission = function () { - $("#dlg-permission").modal("show"); - }; - ctrl.addBookmark = function () { - $("#dlg-bookmark").modal("show"); - }; - ctrl.toggleSidebar = function () { - $(".main-sidebar").toggle(); - $(".sub-sidebar").toggle(); - // $('.navbar-brand').toggle(); - }; - ctrl.clearCache = async function () { - $rootScope.isBusy = true; - await commonService.clearCache(); - $rootScope.showMessage("success", "success"); - $rootScope.isBusy = false; - $scope.$apply(); - }; - ctrl.showHelper = function (url) { - $rootScope.helperUrl = url; - $("#dev-helper-modal").modal("show"); - }; - ctrl.generateSitemap = async function () { - $rootScope.isBusy = true; - var resp = await commonService.genrateSitemap(); - if (resp) { - window.top.location.href = - "/admin/file/details?folder=" + - resp.fileFolder + - "&filename=" + - resp.filename + - resp.extension; - } else { - $rootScope.isBusy = false; - $rootScope.showErrors(["Server error"]); - } - }; - }, - ], - bindings: { - breadCrumbs: "=", - settings: "=", - }, - }); -})(window.angular); - modules.component("highFrequencyMessages", { templateUrl: "/mix-app/views/app-portal/components/high-frequency-messages/view.html", @@ -11424,300 +11094,109 @@ app.controller("HighFrequencyMessagesController", [ }, ]); -// const { data } = require("jquery"); - -modules.component("listMixColumn", { - templateUrl: "/mix-app/views/app-portal/components/list-mix-column/view.html", - bindings: { - header: "=", - columns: "=", - relationships: "=", - removeAttributes: "=", - mixDbDatabaseId: "=?", - namingConvention: "=?", - }, - controller: [ - "$rootScope", - "$scope", - "$routeParams", - "ngAppSettings", - "RestMixRelationshipPortalService", - "RestMixDbTablePortalService", - "RestMixDbColumnPortalService", - function ( - $rootScope, - $scope, - $routeParams, - ngAppSettings, - relationshipService, - databaseService, - service - ) { - var ctrl = this; - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.selectedCol = null; - ctrl.relationshipTypes = ["OneToMany", "ManyToMany"]; - ctrl.defaultRelationship = { - parentId: null, - type: "OneToMany", - childId: null, - displayName: null, - }; - - ctrl.$onInit = async function () { - ctrl.dataTypes = $rootScope.globalSettings.dataTypes; - ctrl.request.mixDbDatabaseId = ctrl.mixDbDatabaseId; - ctrl.updateNamingConvention(); - ctrl.databases = await databaseService.getList(ctrl.request); - var getDefaultAttr = await service.getDefault(); - if (getDefaultAttr.success) { - ctrl.defaultAttr = getDefaultAttr.data; - ctrl.defaultAttr.options = []; - } - angular.forEach(ctrl.relationships, (e, i) => { - e.database = ctrl.databases.data.items.find((m) => m.id == e.childId); - }); - $rootScope.sortArray(ctrl.columns, "priority"); - $scope.$apply(); - }; - ctrl.addColumn = function ( - colName = undefined, - dataType = undefined, - required = false, - defaultValue = undefined - ) { - if (ctrl.columns) { - var t = angular.copy(ctrl.defaultAttr); - t.priority = ctrl.columns.length + 1; - t.columnConfigurations.isRequire = required; - t.defaultValue = defaultValue; - if (colName) { - t.displayName = colName; - t.systemName = colName; - } - if (dataType) { - t.dataType = dataType; - } - if (defaultValue) { - t.defaultValue = defaultValue; - } - ctrl.columns.push(t); - } - }; - ctrl.addDefaultColumns = () => { - ctrl.addColumn(ctrl.fieldNames.id, "Integer", true); - ctrl.addColumn(ctrl.fieldNames.createdBy, "String"); - ctrl.addColumn(ctrl.fieldNames.modifiedByBy, "String"); - ctrl.addColumn(ctrl.fieldNames.createdDateTime, "DateTime", true); - ctrl.addColumn(ctrl.fieldNames.lastModified, "DateTime", true); - ctrl.addColumn(ctrl.fieldNames.priority, "Integer", false, 0); - }; - ctrl.showModal = (id) => { - $(`#advance-${id}`).modal("toggle"); - }; - ctrl.selectReferenceDb = function (relationship) { - relationship.childId = relationship.database.id; - relationship.destinateDatabaseName = relationship.database.systemName; - }; - ctrl.addRelationship = function () { - if (ctrl.relationships) { - var t = angular.copy(ctrl.defaultRelationship); - t.priority = ctrl.relationships.length + 1; - ctrl.relationships.push(t); - } - }; - ctrl.alterColumn = async function (col) { - if (confirm("Alter this column ?")) { - if (col) { - col.isDrop = true; - $rootScope.isBusy = true; - var result = await service.alterColumn(col); - if (result.success) { - $rootScope.showMessage("success", "success"); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - } - }; - ctrl.removeAttribute = async function (attr, index) { - if (confirm("Remove this column ?")) { - if (attr.id) { - $rootScope.isBusy = true; - var remove = await service.delete([attr.id]); - if (remove.success) { - ctrl.columns.splice(index, 1); - } - $rootScope.isBusy = false; +(function (angular) { + app.component("headerNav", { + templateUrl: + "/mix-app/views/app-portal/components/header-nav/headerNav.html", + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "localStorageService", + "CommonService", + "ApiService", + "AuthService", + "CultureService", + function ( + $rootScope, + $scope, + ngAppSettings, + localStorageService, + commonService, + apiService, + authService, + cultureService + ) { + var ctrl = this; + ctrl.appSettings = $rootScope.globalSettings; + ctrl.isInRole = $rootScope.isInRole; + this.$onInit = function () { + ctrl.isAdmin = $rootScope.isAdmin; + ctrl.mixConfigurations = $rootScope.mixConfigurations; + cultureService.getList(ngAppSettings.request).then((resp) => { + ctrl.cultures = resp.data.items; + ctrl.selectedCulture = ctrl.cultures.find( + (m) => + m.specificulture == $rootScope.globalSettings.defaultCulture + ); $scope.$apply(); - } else { - ctrl.columns.splice(index, 1); - } - } - }; - ctrl.removeRelationship = async function (rel, index) { - if (confirm("Remove this relationship ?")) { - if (rel.id) { - $rootScope.isBusy = true; - var remove = await relationshipService.delete([rel.id]); - if (remove.success) { - ctrl.relationships.splice(index, 1); + }); + authService.fillAuthData().then(() => { + if ( + authService.authentication && + authService.authentication.info.userData + ) { + ctrl.avatar = authService.authentication.info.userData.avatar; } - $rootScope.isBusy = false; - $scope.$apply(); - } else { - ctrl.relationships.splice(index, 1); - } - } - }; - ctrl.addOption = function (col, index) { - var val = $("#option_" + index).val(); - col.columnConfigurations.allowedValues = - col.columnConfigurations.allowedValues || []; - col.columnConfigurations.allowedValues.push(val); - $("#option_" + index).val(""); - }; - ctrl.generateForm = function () { - var formHtml = document.createElement("module-form"); - formHtml.setAttribute("class", "row"); - angular.forEach(ctrl.viewmodel.attributes, function (e, i) { - var el; - var label = document.createElement("label"); - label.setAttribute("class", "form-label"); - label.setAttribute("ng-bind", "{{data.title}}"); - - switch (e.dataType) { - case "datetime": - el = document.createElement("input"); - el.setAttribute("type", "datetime-local"); - break; - - case "date": - el = document.createElement("input"); - el.setAttribute("type", "date"); - break; - - case "time": - el = document.createElement("input"); - el.setAttribute("type", "time"); - break; - - case "phonenumber": - el = document.createElement("input"); - el.setAttribute("type", "tel"); - break; - - case "number": - el = document.createElement("input"); - el.setAttribute("type", "number"); - break; - - case "html": - el = document.createElement("trumbowyg"); - el.setAttribute("options", "{}"); - el.setAttribute("type", "number"); - break; - - case "textarea": - el = document.createElement("textarea"); - break; - - default: - el = document.createElement("input"); - el.setAttribute("type", "text"); - formHtml.appendChild(el); - break; - } - el.setAttribute("ng-model", "data.jItem[" + e.name + "].value"); - el.setAttribute("placeholder", "{{$ctrl.title}}"); - formHtml.appendChild(label); - formHtml.appendChild(el); - }); - ctrl.viewmodel.formView.content = formHtml.innerHTML; - }; - ctrl.updateNamingConvention = () => { - ctrl.fieldNames = { - id: ctrl.namingConvention == "TitleCase" ? "Id" : "id", - parentId: - ctrl.namingConvention == "TitleCase" ? "ParentId" : "parent_id", - parentDatabaseName: - ctrl.namingConvention == "TitleCase" - ? "ParentDatabaseName" - : "parent_database_name", - childId: - ctrl.namingConvention == "TitleCase" ? "ChildId" : "child_id", - childDatabaseName: - ctrl.namingConvention == "TitleCase" - ? "ChildDatabaseName" - : "child_database_name", - createdDateTime: - ctrl.namingConvention == "TitleCase" - ? "CreatedDateTime" - : "created_date_time", - lastModified: - ctrl.namingConvention == "TitleCase" - ? "LastModified" - : "last_modified", - tenantId: - ctrl.namingConvention == "TitleCase" ? "TenantId" : "mix_tenant_id", - createdBy: - ctrl.namingConvention == "TitleCase" ? "CreatedBy" : "created_by", - modifiedBy: - ctrl.namingConvention == "TitleCase" ? "ModifiedBy" : "modified_by", - priority: - ctrl.namingConvention == "TitleCase" ? "Priority" : "priority", - status: ctrl.namingConvention == "TitleCase" ? "Status" : "status", - isDeleted: - ctrl.namingConvention == "TitleCase" ? "IsDeleted" : "is_deleted", + }); }; - }; - ctrl.generateName = function (col, isForce = false) { - if (isForce || !col.systemName) { - col.systemName = $rootScope.generateKeyword( - col.displayName, - ctrl.namingConvention == "TitleCase" ? "" : "_", - ctrl.namingConvention == "TitleCase", - false - ); - } - }; - ctrl.removeAttr = function (index) { - if (ctrl.columns) { - ctrl.columns.splice(index, 1); - } - }; - ctrl.updateOrders = function (index) { - if (index > ctrl.dragStartIndex) { - ctrl.columns.splice(ctrl.dragStartIndex, 1); - } else { - ctrl.columns.splice(ctrl.dragStartIndex + 1, 1); - } - angular.forEach(ctrl.columns, function (e, i) { - e.priority = i; - }); - $scope.$apply(); - }; - ctrl.dragStart = function (index) { - ctrl.dragStartIndex = index; - }; - ctrl.showReferences = function (col) { - ctrl.colRef = col; - $("#modal-navs").modal("show"); - }; - ctrl.showRelationships = function () { - $("#modal-relationships").modal("show"); - }; - - ctrl.referenceCallback = function (selected) { - if (selected && selected.length) { - ctrl.colRef.reference = selected; - ctrl.colRef.referenceId = selected[0].id; - } - $("#modal-navs").modal("hide"); - }; + ctrl.translate = $rootScope.translate; + ctrl.getConfiguration = function (keyword, isWrap, defaultText) { + return $rootScope.getConfiguration(keyword, isWrap, defaultText); + }; + ctrl.changeLang = function (culture) { + $rootScope.globalSettings.defaultCulture = culture.specificulture; + localStorageService.set("globalSettings", $rootScope.globalSettings); + window.top.location = location.href; + }; + ctrl.logOut = function () { + $rootScope.logOut(); + }; + ctrl.addPermission = function () { + $("#dlg-permission").modal("show"); + }; + ctrl.addBookmark = function () { + $("#dlg-bookmark").modal("show"); + }; + ctrl.toggleSidebar = function () { + $(".main-sidebar").toggle(); + $(".sub-sidebar").toggle(); + // $('.navbar-brand').toggle(); + }; + ctrl.clearCache = async function () { + $rootScope.isBusy = true; + await commonService.clearCache(); + $rootScope.showMessage("success", "success"); + $rootScope.isBusy = false; + $scope.$apply(); + }; + ctrl.showHelper = function (url) { + $rootScope.helperUrl = url; + $("#dev-helper-modal").modal("show"); + }; + ctrl.generateSitemap = async function () { + $rootScope.isBusy = true; + var resp = await commonService.genrateSitemap(); + if (resp) { + window.top.location.href = + "/admin/file/details?folder=" + + resp.fileFolder + + "&filename=" + + resp.filename + + resp.extension; + } else { + $rootScope.isBusy = false; + $rootScope.showErrors(["Server error"]); + } + }; + }, + ], + bindings: { + breadCrumbs: "=", + settings: "=", }, - ], -}); + }); +})(window.angular); modules.component("hubMessages", { templateUrl: @@ -11773,220 +11252,14 @@ app.controller("HubMessagesController", [ (value, index, array) => array.indexOf(array.find((u) => u.username == value.username)) === index - ); - $scope.$apply(); - break; - case "NewMember": - $scope.newMember(msg.data); - break; - case "MemberOffline": - $scope.removeMember(msg.data); - case "NewMessage": - $scope.newMessage(msg); - break; - } - }; - $scope.newMessage = function (msg) { - msg.style = $scope.getMessageType(msg.type); - if ( - msg.data && - !angular.isObject(msg.data) && - msg.data.indexOf("{") == 0 - ) { - msg.data = JSON.parse(msg.data); - } - $scope.messages.push(msg); - if ( - msg.from || - msg.from.connectionId != $scope.hubRequest.from.connectionId - ) { - $scope.newMsgCount += 1; - $rootScope.showMessage(msg.message, msg.style); - } - $scope.$apply(); - }; - $scope.removeMember = function (member) { - var index = $scope.members.findIndex( - (x) => x.username === member.username - ); - if (index >= 0) { - $scope.members.splice(index, 1); - } - $scope.$apply(); - }; - - $scope.newMember = function (member) { - var index = $scope.members.findIndex( - (x) => x.username === member.username - ); - if (index < 0) { - $scope.members.splice(0, 0, member); - } - $scope.$apply(); - }; - $scope.getMessageType = function (type) { - switch (type) { - case "Success": - return "success"; - case "Error": - return "danger"; - case "Warning": - return "warning"; - case "Info": - return "info"; - default: - return "default"; - } - }; - }, -]); - -modules.component("jumbotrons", { - templateUrl: - "/mix-app/views/app-portal/components/jumbotrons/jumbotrons.html", - controller: [ - "$rootScope", - "$scope", - "$location", - function ($rootScope, $scope, $location) { - var ctrl = this; - ctrl.translate = function (keyword) { - return $rootScope.translate(keyword); - }; - // ctrl.back = function () { - // ctrl.backUrl = ctrl.backUrl || '/admin'; - // $location.path(ctrl.backUrl); - // }; - }, - ], - bindings: { - tagName: "=", - tagType: "=", - }, -}); - -modules.component("mainSideBar", { - templateUrl: - "/mix-app/views/app-portal/components/main-side-bar/main-side-bar.html", - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - "TranslatorService", - "ApiService", - "CommonService", - function ( - $rootScope, - $scope, - ngAppSettings, - translatorService, - apiService, - commonService - ) { - var ctrl = this; - ctrl.items = []; - ctrl.init = async function () { - var resp = await apiService.getPortalMenus(); - if (resp.success && resp.data && resp.data.length) { - ctrl.items = resp.data; - } else { - ctrl.items = JSON.parse($("#portal-menus").val()).items; - } - }; - }, - ], - bindings: { - items: "=?", - }, -}); - -modules.component("mainSideBarDynamic", { - templateUrl: - "/mix-app/views/app-portal/components/main-side-bar-dynamic/main-side-bar-dynamic.html", - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - "CommonService", - "TranslatorService", - "AuthService", - function ( - $rootScope, - $scope, - ngAppSettings, - commonService, - translatorService, - authService - ) { - var ctrl = this; - ctrl.init = function () { - // commonService.getPermissions().then(function (response) { - // if (response && response.success) { - // ctrl.isInit = true; - // ctrl.roles = response.data; - // if (ctrl.roles.data) { - // ctrl.role = ctrl.roles.data[0]; - // } - // $rootScope.isBusy = false; - // $scope.$apply(); - // } - // }); - }; - }, - ], - bindings: { - roles: "=", - activedRole: "=", - translate: "&", - }, -}); - -modules.component("logStream", { - templateUrl: "/mix-app/views/app-portal/components/log-stream/view.html", - controller: "LogStreamController", - bindings: {}, -}); -app.controller("LogStreamController", [ - "$scope", - "$rootScope", - "AuthService", - function ($scope, $rootScope, authService) { - var endpoints = JSON.parse(localStorage.getItem("ls.endpoints") || "{}"); - BaseHub.call(this, $scope, endpoints.Messenger); - - authService.fillAuthData(); - $scope.keyword = ""; - $scope.newMsgCount = 0; - $scope.messages = []; - $scope.onConnected = () => { - // $scope.joinRoom("portal"); - }; - $scope.init = function () { - $scope.startConnection( - "log-stream-hub", - authService.authentication.accessToken, - (err) => { - if ( - authService.authentication.refreshToken && - err.message.indexOf("401") >= 0 - ) { - authService.refreshToken().then(async () => { - $scope.startConnection( - "log-stream-hub", - authService.authentication.accessToken - ); - }); - } - } - ); - }; - $scope.readMessages = function () { - $scope.newMsgCount = 0; - $("#modal-log-stream").modal("show"); - $scope.scrollToBot(); - }; - $scope.receiveMessage = function (msg) { - switch (msg.action) { + ); + $scope.$apply(); + break; + case "NewMember": + $scope.newMember(msg.data); + break; + case "MemberOffline": + $scope.removeMember(msg.data); case "NewMessage": $scope.newMessage(msg); break; @@ -12002,27 +11275,39 @@ app.controller("LogStreamController", [ msg.data = JSON.parse(msg.data); } $scope.messages.push(msg); + if ( + msg.from || + msg.from.connectionId != $scope.hubRequest.from.connectionId + ) { + $scope.newMsgCount += 1; + $rootScope.showMessage(msg.message, msg.style); + } $scope.$apply(); - $scope.scrollToBot(); }; - $scope.scrollToBot = () => { - let container = $("#modal-log-stream").find(".modal-body")[0]; - setTimeout(() => { - let h = $("#modal-log-stream").find(".table").height(); - $(container).animate( - { - scrollTop: h, // Scroll to top of body - }, - 500 - ); - }, 200); + $scope.removeMember = function (member) { + var index = $scope.members.findIndex( + (x) => x.username === member.username + ); + if (index >= 0) { + $scope.members.splice(index, 1); + } + $scope.$apply(); + }; + + $scope.newMember = function (member) { + var index = $scope.members.findIndex( + (x) => x.username === member.username + ); + if (index < 0) { + $scope.members.splice(0, 0, member); + } + $scope.$apply(); }; $scope.getMessageType = function (type) { switch (type) { case "Success": return "success"; case "Error": - $scope.newMsgCount += 1; return "danger"; case "Warning": return "warning"; @@ -12035,824 +11320,1088 @@ app.controller("LogStreamController", [ }, ]); -modules.component("mainSideBarItem", { +modules.component("jumbotrons", { templateUrl: - "/mix-app/views/app-portal/components/main-side-bar-item/main-side-bar-item.html", + "/mix-app/views/app-portal/components/jumbotrons/jumbotrons.html", controller: [ "$rootScope", - function ($rootScope) { + "$scope", + "$location", + function ($rootScope, $scope, $location) { var ctrl = this; - ctrl.translate = $rootScope.translate; - ctrl.addClass = function (obj) { - obj.currentTarget.classList.add("btn-group-lg"); - //alert(obj); - }; - ctrl.removeClass = function (obj) { - obj.currentTarget.classList.remove("btn-group-lg"); - //alert(obj); + ctrl.translate = function (keyword) { + return $rootScope.translate(keyword); }; + // ctrl.back = function () { + // ctrl.backUrl = ctrl.backUrl || '/admin'; + // $location.path(ctrl.backUrl); + // }; }, ], bindings: { - item: "=", - }, -}); - -modules.component("mainSideBarItemDynamic", { - templateUrl: - "/mix-app/views/app-portal/components/main-side-bar-item-dynamic/main-side-bar-item-dynamic.html", - controller: [ - "$rootScope", - function ($rootScope) { - var ctrl = this; - ctrl.translate = $rootScope.translate; - }, - ], - bindings: { - iconSize: "=", - linkStyle: "=", - itemStyle: "=", - item: "=", + tagName: "=", + tagType: "=", }, }); -modules.component("mediumNews", { - templateUrl: "/mix-app/views/app-portal/components/medium-news/view.html", - controller: [ - "$rootScope", - "$http", - function ($rootScope, $http) { - var ctrl = this; - ctrl.items = []; - ctrl.init = function () { - var req = { - method: "GET", - url: - "https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/mixcore&api_key=qww481wpgat3g4iqvqss7spzrilkbekpxpjgrbof&t=" + - Math.floor(Date.now() / 1000), - }; - ctrl.getMediumApiResult(req); - }; - - ctrl.getMediumApiResult = async function (req) { - return $http(req).then( - function (resp) { - if (resp.status == "200") { - ctrl.items = resp.data.items; - } - }, - function (error) { - return { - success: false, - errors: [error.statusText || error.status], - }; - } - ); - }; - }, - ], - bindings: {}, -}); - -modules.component("mediaFileUpload", { - templateUrl: - "/mix-app/views/app-portal/components/media-file-upload/view.html", +modules.component("jsonBuilder", { + templateUrl: "/mix-app/views/app-portal/components/json-builder/view.html", bindings: { - header: "=?", - accept: "=?", - src: "=", - srcUrl: "=?", - fileModel: "=?", - type: "=?", - auto: "=?", - uploadOptions: "=?", - onDelete: "&?", - onUpdate: "&?", - onInsert: "&?", + data: "=?", // json obj (ex: { column1: 'some val' }) + strData: "=?", // json obj (ex: { column1: 'some val' }) + folder: "=?", // filepath (ex: 'data/jsonfile.json') + filename: "=?", // filepath (ex: 'data/jsonfile.json') + allowedTypes: "=?", // string array ( ex: [ 'type1', 'type2' ] ) + backUrl: "=?", // string array ( ex: [ 'type1', 'type2' ] ) + showPreview: "=?", + type: "=?", // array / obj + editMode: "=?", // array / obj + save: "&", + onUpdate: "&", }, controller: [ "$rootScope", "$scope", + "$location", + "FileServices", "ngAppSettings", - "MediaService", - function ($rootScope, $scope, ngAppSettings, mediaService) { + function ($rootScope, $scope, $location, fileService, ngAppSettings) { var ctrl = this; - ctrl.isAdmin = $rootScope.isAdmin; - var image_placeholder = "/mix-app/assets/img/image_placeholder.jpg"; - ctrl.isImage = false; - ctrl.mediaNavs = []; - ctrl.$onInit = function () { - ctrl.autoSave = ctrl.auto === "true"; - if (ctrl.src) { - ctrl.srcUrl = angular.copy(ctrl.src); - } - // if (!ctrl.srcUrl) { - // ctrl.srcUrl = image_placeholder; - // } - ctrl.isImage = - ctrl.srcUrl != undefined && - ctrl.srcUrl - .toLowerCase() - .match(/([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|svg|webp)/g); - ctrl.maxHeight = ctrl.maxHeight || "200px"; - ctrl.id = Math.floor(Math.random() * 100); - if (ctrl.uploadOptions) { - ctrl.w = ctrl.uploadOptions.width; - ctrl.h = ctrl.uploadOptions.height; - } + + ctrl.file = null; + ctrl.translate = $rootScope.translate; + ctrl.mixConfigurations = $rootScope.globalSettings; + ctrl.timestamp = Math.random(); + ctrl.templates = [ + { + type: "item", + name: "", + dataType: "Text", + value: "", + columns: [{ allowedTypes: ["item"], items: [] }], + }, + { + type: "string", + dataType: "Text", + value: "", + columns: [{ allowedTypes: ["item"], items: [] }], + }, + { + type: "object", + name: "o1", + columns: [{ allowedTypes: ["array", "object", "item"], items: [] }], + }, + { + type: "array", + name: "a1", + columns: [{ allowedTypes: ["object"], items: [] }], + }, + ]; + ctrl.draft = []; + ctrl.model = {}; + ctrl.dropzones = { + root: [], }; - ctrl.$doCheck = function () { - if (ctrl.src !== ctrl.srcUrl && ctrl.srcUrl != image_placeholder) { - ctrl.src = ctrl.srcUrl; - ctrl.isImage = ctrl.srcUrl - .toLowerCase() - .match(/([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|svg)/g); + ctrl.selected = null; + ctrl.selectedModel = {}; + ctrl.strModel = null; + ctrl.init = async function () { + var arr = []; + if (!ctrl.editMode) { + ctrl.editMode = "json"; } - }.bind(ctrl); - - ctrl.selectFile = function (files) { - if (files !== undefined && files !== null && files.length > 0) { - ctrl.formFile = files[0]; - if ( - ctrl.uploadOptions && - ctrl.uploadOptions.isCrop && - $rootScope.isImage(ctrl.formFile) - ) { - ctrl.canUpload = false; - mediaService.openCroppie(files[0], ctrl, ctrl.autoSave); - } else { - ctrl.canUpload = true; - if (ctrl.autoSave) { - ctrl.uploadFile(ctrl.formFile); - } else { - ctrl.getBase64(ctrl.formFile); + if (!ctrl.data && ctrl.filename) { + await ctrl.loadFile(); + ctrl.parseObjToList(ctrl.data, arr); + ctrl.dropzones.root = arr; + } else { + if (!ctrl.data) { + if (ctrl.strData) { + ctrl.data = JSON.parse(ctrl.strData); + } + if (!ctrl.data && ctrl.type) { + ctrl.data = ctrl.type == "array" ? [] : {}; } } + ctrl.rootType = Array.isArray(ctrl.data) ? "array" : "object"; + ctrl.parseObjToList(ctrl.data, arr); + ctrl.strData = JSON.stringify(ctrl.data); + ctrl.dropzones.root = arr; + ctrl.preview = angular.copy(ctrl.data); } }; + ctrl.loadFile = async function () { + $rootScope.isBusy = true; + $scope.listUrl = "/admin/json-data/list?folder=" + ctrl.folder; - ctrl.croppieCallback = function (result) { - if (result) { - ctrl.isImage = true; - if (!ctrl.autoSave) { - ctrl.src = result; - ctrl.fileBase64 = result; - } else { - ctrl.src = result; - ctrl.srcUrl = result; - } - } else if (ctrl.formFile) { - if (ctrl.autoSave) { - ctrl.uploadFile(ctrl.formFile); + var response = await fileService.getFile(ctrl.folder, ctrl.filename); + if (response.success) { + ctrl.file = response.data; + ctrl.data = JSON.parse(response.data.content); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + ctrl.saveFile = async function () { + $rootScope.isBusy = true; + ctrl.model = {}; + ctrl.update(); + if (ctrl.save) { + ctrl.save({ data: ctrl.model }); + } else { + // ctrl.parseObj(ctrl.dropzones.root, ctrl.model); + ctrl.file.content = JSON.stringify(ctrl.model); + var resp = await fileService.saveFile(ctrl.file); + if (resp && resp.success) { + $scope.activedFile = resp.data; + $rootScope.showMessage("Update successfully!", "success"); + $rootScope.isBusy = false; + $scope.$apply(); } else { - ctrl.fileModel.file = ctrl.formFile; - ctrl.getBase64(ctrl.formFile); + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); } - // ctrl.uploadFile(ctrl.formFile); } + ctrl.select(ctrl.selected); }; - - ctrl.uploadFile = async function (file) { - if (file !== null) { - $rootScope.isBusy = true; - if (file) { - ctrl.srcUrl = null; - var response = await mediaService.uploadMedia( - file, - null, - ctrl.onUploadFileProgress - ); - if (response.success) { - ctrl.media = response.data.url; - $rootScope.isBusy = false; - ctrl.srcUrl = response.data.url; - $scope.$apply(); + ctrl.update = function () { + ctrl.model = {}; + var obj = { + type: "object", + name: "data", + columns: [ + { + items: ctrl.dropzones.root, + }, + ], + }; + ctrl.parseObj(obj, ctrl.model); + ctrl.strData = JSON.stringify(ctrl.model); + ctrl.onUpdate({ data: ctrl.model }); + }; + ctrl.updateJsonContent = function (strData) { + if (strData) { + ctrl.model = JSON.parse(strData); + ctrl.strData = strData; + ctrl.onUpdate({ data: ctrl.model }); + } + }; + ctrl.parseObjToList = function (item, items) { + // key: the name of the object key + // index: the ordinal position of the key within the object + if (Array.isArray(item)) { + angular.forEach(item, (e) => { + var obj = angular.copy(ctrl.templates[1]); + obj.value = e; + // ctrl.parseObjToList(e, obj.columns[0].items); + items.push(obj); + }); + } else { + Object.keys(item).forEach(function (key) { + var obj = {}; + if (item[key]) { + var objType = typeof item[key]; + switch (objType) { + case "object": + if (Array.isArray(item[key])) { + obj = angular.copy(ctrl.templates[2]); + obj.name = key; + ctrl.parseObjToList(item[key], obj.columns[0].items); + items.push(obj); + } else { + obj = angular.copy(ctrl.templates[1]); + obj.name = key; + ctrl.parseObjToList(item[key], obj.columns[0].items); + items.push(obj); + } + break; + default: + obj = angular.copy(ctrl.templates[0]); + obj.name = key; + obj.value = item[key]; + items.push(obj); + break; + } + } + }); + } + }; + ctrl.parseObj = function (item, obj, name) { + switch (item.type) { + case "array": + obj[item.name] = []; + angular.forEach(item.columns[0].items, (sub) => { + var o = {}; + ctrl.parseObj(sub, o); + obj[item.name].push(o); + }); + break; + case "object": + angular.forEach(item.columns[0].items, (sub) => { + if (sub.type == "object") { + var o = {}; + ctrl.parseObj(sub, o); + obj[item.name] = o; + } else { + ctrl.parseObj(sub, obj, item.name); + } + }); + break; + case "item": + obj[item.name] = item.value; + break; + } + }; + ctrl.parseJsonObject = function () { + if (ctrl.rootType == "object") { + ctrl.data = {}; + angular.forEach(ctrl.dropzones.root, (sub) => { + if (sub.type == "object") { + var o = {}; + ctrl.parseObj(sub, o); + ctrl.data[sub.name] = o; } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); + ctrl.data[sub.name] = sub.value; } - } + }); } else { - return null; + ctrl.data = []; + if (ctrl.rootType == "array") { + angular.forEach(ctrl.dropzones.root, (sub) => { + ctrl.data.push(sub.value); + }); + } } + ctrl.strData = JSON.stringify(ctrl.data); + ctrl.onUpdate({ data: JSON.stringify(ctrl.data) }); }; - ctrl.getBase64 = function (file) { - if (file !== null) { - $rootScope.isBusy = true; - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function () { - if (ctrl.fileModel) { - ctrl.fileModel.filename = file.name.substring( - 0, - file.name.lastIndexOf(".") - ); - ctrl.fileModel.extension = file.name.substring( - file.name.lastIndexOf(".") - ); - ctrl.fileModel.fileBase64 = reader.result; - } - ctrl.srcUrl = reader.result; - ctrl.isImage = - ctrl.srcUrl.indexOf("data:image/") >= 0 || - ctrl.srcUrl - .toLowerCase() - .match(/([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|svg)/g); - ctrl.src = reader.result; - $rootScope.isBusy = false; - $scope.$apply(); - }; - reader.onerror = function (error) { - $rootScope.isBusy = false; - $rootScope.showErrors([error]); - }; + ctrl.select = function (item) { + if (ctrl.selected == item) { + ctrl.parseObj(item, ctrl.selectedModel); } else { - return null; + ctrl.selected = item; + ctrl.selectedModel = {}; + ctrl.parseObj(item, ctrl.selectedModel); } + ctrl.timestamp = Math.random(); + }; + ctrl.addField = function () { + var column = angular.copy(ctrl.templates[0]); + ctrl.dropzones.root.push(column); + ctrl.parseJsonObject(); + }; + ctrl.addString = function () { + var column = angular.copy(ctrl.templates[1]); + ctrl.dropzones.root.push(column); + ctrl.parseJsonObject(); + }; + ctrl.addObj = function (item) { + var obj = angular.copy(ctrl.templates[1]); + obj.name = "o" + (item.columns[0].items.length + 1); + item.columns[0].items.push(obj); + item.showMenu = false; + ctrl.parseJsonObject(); + }; + ctrl.addArray = function (item) { + var obj = angular.copy(ctrl.templates[2]); + obj.name = "a" + (item.columns[0].items.length + 1); + item.columns[0].items.push(obj); + item.showMenu = false; + ctrl.parseJsonObject(); + }; + ctrl.clone = function (item, list) { + var obj = angular.copy(item); + obj.name = item.name + "_copy"; + item.showMenu = false; + obj.showMenu = false; + list.items.push(obj); + ctrl.parseJsonObject(); }; - ctrl.onUploadFileProgress = function (progress) { - ctrl.progress = progress; + + ctrl.remove = function (index, list) { + if (confirm("Remove this")) { + list.splice(index, 1); + ctrl.parseJsonObject(); + } }; }, ], }); -modules.component("mixDbDataValueEditor", { - templateUrl: - "/mix-app/views/app-portal/components/mix-db-data-value-editor/view.html", +// const { data } = require("jquery"); + +modules.component("listMixColumn", { + templateUrl: "/mix-app/views/app-portal/components/list-mix-column/view.html", bindings: { - mixDbDataValue: "=?", - parentType: "=?", - parentId: "=?", - isShowTitle: "=?", + header: "=", + columns: "=", + relationships: "=", + removeAttributes: "=", + mixDbDatabaseId: "=?", + namingConvention: "=?", }, controller: [ "$rootScope", "$scope", + "$routeParams", "ngAppSettings", - "$location", - "RestMixAssociationPortalService", - "RestMixDbDataPortalService", + "RestMixRelationshipPortalService", + "RestMixDbTablePortalService", + "RestMixDbColumnPortalService", function ( $rootScope, $scope, + $routeParams, ngAppSettings, - $location, - navService, - dataService + relationshipService, + databaseService, + service ) { var ctrl = this; - ctrl.goToPath = $rootScope.goToPath; - ctrl.icons = ngAppSettings.icons; - ctrl.refData = null; - ctrl.defaultDataModel = null; - ctrl.refDataModel = { - id: null, - data: null, + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.selectedCol = null; + ctrl.relationshipTypes = ["OneToMany", "ManyToMany"]; + ctrl.defaultRelationship = { + parentId: null, + type: "OneToMany", + childId: null, + displayName: null, }; - ctrl.refRequest = angular.copy(ngAppSettings.request); - ctrl.refRequest.pageSize = 100; - ctrl.dataTypes = $rootScope.globalSettings.dataTypes; - ctrl.previousId = null; - ctrl.$doCheck = function () { - if (ctrl.mixDbDataValue && ctrl.previousId !== ctrl.mixDbDataValue.id) { - ctrl.previousId = ctrl.mixDbDataValue.id; - ctrl.initData(); + + ctrl.$onInit = async function () { + ctrl.dataTypes = $rootScope.globalSettings.dataTypes; + ctrl.request.mixDbDatabaseId = ctrl.mixDbDatabaseId; + ctrl.updateNamingConvention(); + ctrl.databases = await databaseService.getList(ctrl.request); + var getDefaultAttr = await service.getDefault(); + if (getDefaultAttr.success) { + ctrl.defaultAttr = getDefaultAttr.data; + ctrl.defaultAttr.options = []; } - }.bind(ctrl); - ctrl.$onInit = function () { - ctrl.initData(); + angular.forEach(ctrl.relationships, (e, i) => { + e.database = ctrl.databases.data.items.find((m) => m.id == e.childId); + }); + $rootScope.sortArray(ctrl.columns, "priority"); + $scope.$apply(); }; - ctrl.initData = async function () { - setTimeout(() => { - if (!ctrl.mixDbDataValue.id) { - ctrl.initDefaultValue(); + ctrl.addColumn = function ( + colName = undefined, + dataType = undefined, + required = false, + defaultValue = undefined + ) { + if (ctrl.columns) { + var t = angular.copy(ctrl.defaultAttr); + t.priority = ctrl.columns.length + 1; + t.columnConfigurations.isRequire = required; + t.defaultValue = defaultValue; + if (colName) { + t.displayName = colName; + t.systemName = colName; } - switch (ctrl.mixDbDataValue.dataType.toLowerCase()) { + if (dataType) { + t.dataType = dataType; + } + if (defaultValue) { + t.defaultValue = defaultValue; + } + ctrl.columns.push(t); + } + }; + ctrl.addDefaultColumns = () => { + ctrl.addColumn(ctrl.fieldNames.id, "Integer", true); + ctrl.addColumn(ctrl.fieldNames.createdBy, "String"); + ctrl.addColumn(ctrl.fieldNames.modifiedByBy, "String"); + ctrl.addColumn(ctrl.fieldNames.createdDateTime, "DateTime", true); + ctrl.addColumn(ctrl.fieldNames.lastModified, "DateTime", true); + ctrl.addColumn(ctrl.fieldNames.priority, "Integer", false, 0); + }; + ctrl.showModal = (id) => { + $(`#advance-${id}`).modal("toggle"); + }; + ctrl.selectReferenceDb = function (relationship) { + relationship.childId = relationship.database.id; + relationship.destinateDatabaseName = relationship.database.systemName; + }; + ctrl.addRelationship = function () { + if (ctrl.relationships) { + var t = angular.copy(ctrl.defaultRelationship); + t.priority = ctrl.relationships.length + 1; + ctrl.relationships.push(t); + } + }; + ctrl.alterColumn = async function (col) { + if (confirm("Alter this column ?")) { + if (col) { + col.isDrop = true; + $rootScope.isBusy = true; + var result = await service.alterColumn(col); + if (result.success) { + $rootScope.showMessage("success", "success"); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + } + }; + ctrl.removeAttribute = async function (attr, index) { + if (confirm("Remove this column ?")) { + if (attr.id) { + $rootScope.isBusy = true; + var remove = await service.delete([attr.id]); + if (remove.success) { + ctrl.columns.splice(index, 1); + } + $rootScope.isBusy = false; + $scope.$apply(); + } else { + ctrl.columns.splice(index, 1); + } + } + }; + ctrl.removeRelationship = async function (rel, index) { + if (confirm("Remove this relationship ?")) { + if (rel.id) { + $rootScope.isBusy = true; + var remove = await relationshipService.delete([rel.id]); + if (remove.success) { + ctrl.relationships.splice(index, 1); + } + $rootScope.isBusy = false; + $scope.$apply(); + } else { + ctrl.relationships.splice(index, 1); + } + } + }; + ctrl.addOption = function (col, index) { + var val = $("#option_" + index).val(); + col.columnConfigurations.allowedValues = + col.columnConfigurations.allowedValues || []; + col.columnConfigurations.allowedValues.push(val); + $("#option_" + index).val(""); + }; + ctrl.generateForm = function () { + var formHtml = document.createElement("module-form"); + formHtml.setAttribute("class", "row"); + angular.forEach(ctrl.viewmodel.attributes, function (e, i) { + var el; + var label = document.createElement("label"); + label.setAttribute("class", "form-label"); + label.setAttribute("ng-bind", "{{data.title}}"); + + switch (e.dataType) { case "datetime": + el = document.createElement("input"); + el.setAttribute("type", "datetime-local"); + break; + case "date": + el = document.createElement("input"); + el.setAttribute("type", "date"); + break; + case "time": - if (ctrl.mixDbDataValue.dateTimeValue) { - ctrl.mixDbDataValue.dateObj = new Date( - ctrl.mixDbDataValue.dateTimeValue - ); - $scope.$apply(); - } + el = document.createElement("input"); + el.setAttribute("type", "time"); break; - case "reference": // reference - if (ctrl.mixDbDataValue.column.referenceId && ctrl.parentId) { - ctrl.mixDbDataValue.integerValue = - ctrl.mixDbDataValue.column.referenceId; - // navService.getSingle(["default"]).then((resp) => { - // ctrl.defaultDataModel = resp; - // ctrl.defaultDataModel.mixDbTableId = - // ctrl.mixDbDataValue.column.referenceId; - // ctrl.refDataModel = angular.copy(ctrl.defaultDataModel); - // }); - // ctrl.loadRefData(); - } + + case "phonenumber": + el = document.createElement("input"); + el.setAttribute("type", "tel"); break; - default: - if ( - ctrl.mixDbDataValue.column && - ctrl.mixDbDataValue.column.isEncrypt && - ctrl.mixDbDataValue.encryptValue - ) { - var encryptedData = { - key: ctrl.mixDbDataValue.encryptKey, - data: ctrl.mixDbDataValue.encryptValue, - }; - ctrl.mixDbDataValue.stringValue = - $rootScope.decrypt(encryptedData); - } - if ( - ctrl.mixDbDataValue.column && - !ctrl.mixDbDataValue.stringValue - ) { - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.column.defaultValue; - $scope.$apply(); - } + + case "number": + el = document.createElement("input"); + el.setAttribute("type", "number"); + break; + + case "html": + el = document.createElement("trumbowyg"); + el.setAttribute("options", "{}"); + el.setAttribute("type", "number"); + break; + + case "textarea": + el = document.createElement("textarea"); + break; + + default: + el = document.createElement("input"); + el.setAttribute("type", "text"); + formHtml.appendChild(el); break; } - }, 200); + el.setAttribute("ng-model", "data.jItem[" + e.name + "].value"); + el.setAttribute("placeholder", "{{$ctrl.title}}"); + formHtml.appendChild(label); + formHtml.appendChild(el); + }); + ctrl.viewmodel.formView.content = formHtml.innerHTML; }; - ctrl.initDefaultValue = async function () { - switch (ctrl.mixDbDataValue.dataType) { - case "datetime": - case "date": - case "time": - if (ctrl.mixDbDataValue.column.defaultValue) { - ctrl.mixDbDataValue.dateObj = new Date( - ctrl.mixDbDataValue.column.defaultValue - ); - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.column.defaultValue; - } - break; - case "double": - if (ctrl.mixDbDataValue.column.defaultValue) { - ctrl.mixDbDataValue.doubleValue = parseFloat( - ctrl.mixDbDataValue.column.defaultValue - ); - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.column.defaultValue; - } - break; - case "boolean": - if (ctrl.mixDbDataValue.column.defaultValue) { - ctrl.mixDbDataValue.booleanValue = - ctrl.mixDbDataValue.column.defaultValue == "true"; - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.column.defaultValue; - } - break; - - default: - if (ctrl.mixDbDataValue.column.defaultValue) { - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.column.defaultValue; - } - break; + ctrl.updateNamingConvention = () => { + ctrl.fieldNames = { + id: ctrl.namingConvention == "TitleCase" ? "Id" : "id", + parentId: + ctrl.namingConvention == "TitleCase" ? "ParentId" : "parent_id", + parentDatabaseName: + ctrl.namingConvention == "TitleCase" + ? "ParentDatabaseName" + : "parent_database_name", + childId: + ctrl.namingConvention == "TitleCase" ? "ChildId" : "child_id", + childDatabaseName: + ctrl.namingConvention == "TitleCase" + ? "ChildDatabaseName" + : "child_database_name", + createdDateTime: + ctrl.namingConvention == "TitleCase" + ? "CreatedDateTime" + : "created_date_time", + lastModified: + ctrl.namingConvention == "TitleCase" + ? "LastModified" + : "last_modified", + tenantId: + ctrl.namingConvention == "TitleCase" ? "TenantId" : "mix_tenant_id", + createdBy: + ctrl.namingConvention == "TitleCase" ? "CreatedBy" : "created_by", + modifiedBy: + ctrl.namingConvention == "TitleCase" ? "ModifiedBy" : "modified_by", + priority: + ctrl.namingConvention == "TitleCase" ? "Priority" : "priority", + status: ctrl.namingConvention == "TitleCase" ? "Status" : "status", + isDeleted: + ctrl.namingConvention == "TitleCase" ? "IsDeleted" : "is_deleted", + }; + }; + ctrl.generateName = function (col, isForce = false) { + if (isForce || !col.systemName) { + col.systemName = $rootScope.generateKeyword( + col.displayName, + ctrl.namingConvention == "TitleCase" ? "" : "_", + ctrl.namingConvention == "TitleCase", + false + ); } }; - ctrl.updateStringValue = async function (dataType) { - switch (dataType.toLowerCase()) { - case "datetime": - case "date": - case "time": - if (ctrl.mixDbDataValue.dateObj) { - ctrl.mixDbDataValue.dateTimeValue = - ctrl.mixDbDataValue.dateObj.toISOString(); - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.dateTimeValue; - } - break; - case "double": - if (ctrl.mixDbDataValue.doubleValue) { - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.doubleValue.toString(); - } - break; - case "boolean": - if (ctrl.mixDbDataValue.booleanValue != null) { - ctrl.mixDbDataValue.stringValue = - ctrl.mixDbDataValue.booleanValue.toString(); - } - break; - - default: - break; + ctrl.removeAttr = function (index) { + if (ctrl.columns) { + ctrl.columns.splice(index, 1); } }; - - ctrl.updateRefData = function (nav) { - ctrl.goToPath(`/admin/mix-db-data/details?dataContentId=${nav.data.id} - &mixDbTableId=${nav.data.mixDbTableId} - &parentId=${ctrl.parentId} - &parentType=${ctrl.parentType}`); - // ctrl.refDataModel = nav; - // var e = $(".pane-form-" + ctrl.mixDbDataValue.column.referenceId)[0]; - // angular.element(e).triggerHandler('click'); - // $location.url('/admin/mix-db-data/details?dataContentId='+ item.id +'&mixDbTableId=' + item.mixDbTableId+'&parentType=' + item.parentType+'&parentId=' + item.parentId); + ctrl.updateOrders = function (index) { + if (index > ctrl.dragStartIndex) { + ctrl.columns.splice(ctrl.dragStartIndex, 1); + } else { + ctrl.columns.splice(ctrl.dragStartIndex + 1, 1); + } + angular.forEach(ctrl.columns, function (e, i) { + e.priority = i; + }); + $scope.$apply(); }; - - ctrl.removeRefData = async function (nav) { - $rootScope.showConfirm( - ctrl, - "removeRefDataConfirmed", - [nav], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); + ctrl.dragStart = function (index) { + ctrl.dragStartIndex = index; }; - ctrl.removeRefDataConfirmed = async function (nav) { - $rootScope.isBusy = true; - var result = await navService.delete([ - nav.parentId, - nav.parentType, - nav.id, - ]); - if (result.success) { - $rootScope.removeObjectByKey(ctrl.refData, "id", nav.id); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErros(result.errors); - $rootScope.isBusy = false; - $scope.$apply(); + ctrl.showReferences = function (col) { + ctrl.colRef = col; + $("#modal-navs").modal("show"); + }; + ctrl.showRelationships = function () { + $("#modal-relationships").modal("show"); + }; + + ctrl.referenceCallback = function (selected) { + if (selected && selected.length) { + ctrl.colRef.reference = selected; + ctrl.colRef.referenceId = selected[0].id; } + $("#modal-navs").modal("hide"); }; }, ], }); -modules.component("mediaUpload", { +modules.component("logStream", { + templateUrl: "/mix-app/views/app-portal/components/log-stream/view.html", + controller: "LogStreamController", + bindings: {}, +}); +app.controller("LogStreamController", [ + "$scope", + "$rootScope", + "AuthService", + function ($scope, $rootScope, authService) { + var endpoints = JSON.parse(localStorage.getItem("ls.endpoints") || "{}"); + BaseHub.call(this, $scope, endpoints.Messenger); + + authService.fillAuthData(); + $scope.keyword = ""; + $scope.newMsgCount = 0; + $scope.messages = []; + $scope.onConnected = () => { + // $scope.joinRoom("portal"); + }; + $scope.init = function () { + $scope.startConnection( + "log-stream-hub", + authService.authentication.accessToken, + (err) => { + if ( + authService.authentication.refreshToken && + err.message.indexOf("401") >= 0 + ) { + authService.refreshToken().then(async () => { + $scope.startConnection( + "log-stream-hub", + authService.authentication.accessToken + ); + }); + } + } + ); + }; + $scope.readMessages = function () { + $scope.newMsgCount = 0; + $("#modal-log-stream").modal("show"); + $scope.scrollToBot(); + }; + $scope.receiveMessage = function (msg) { + switch (msg.action) { + case "NewMessage": + $scope.newMessage(msg); + break; + } + }; + $scope.newMessage = function (msg) { + msg.style = $scope.getMessageType(msg.type); + if ( + msg.data && + !angular.isObject(msg.data) && + msg.data.indexOf("{") == 0 + ) { + msg.data = JSON.parse(msg.data); + } + $scope.messages.push(msg); + $scope.$apply(); + $scope.scrollToBot(); + }; + $scope.scrollToBot = () => { + let container = $("#modal-log-stream").find(".modal-body")[0]; + setTimeout(() => { + let h = $("#modal-log-stream").find(".table").height(); + $(container).animate( + { + scrollTop: h, // Scroll to top of body + }, + 500 + ); + }, 200); + }; + $scope.getMessageType = function (type) { + switch (type) { + case "Success": + return "success"; + case "Error": + $scope.newMsgCount += 1; + return "danger"; + case "Warning": + return "warning"; + case "Info": + return "info"; + default: + return "default"; + } + }; + }, +]); + +modules.component("mainSideBar", { templateUrl: - "/mix-app/views/app-portal/components/media-upload/media-upload.html", + "/mix-app/views/app-portal/components/main-side-bar/main-side-bar.html", controller: [ - "$scope", "$rootScope", - "MediaService", + "$scope", + "ngAppSettings", + "TranslatorService", "ApiService", "CommonService", - function ($scope, $rootScope, service, apiService, commonService) { + function ( + $rootScope, + $scope, + ngAppSettings, + translatorService, + apiService, + commonService + ) { var ctrl = this; - ctrl.default = { - title: "", - description: "", - status: "Published", - fileFolder: "Medias", - mediaFile: { - file: null, - fullPath: "", - folderName: "Media", - fileFolder: "", - fileName: "", - extension: "", - content: "", - fileBase64: "", - }, - }; - ctrl.viewmodel = angular.copy(ctrl.default); - ctrl.onInsert = function (data) { - if (ctrl.onUpdate) { - ctrl.onUpdate(); - } - }; - ctrl.save = async function (data) { - $rootScope.isBusy = true; - var resp = await service.save(data); - if (resp && resp.success) { - $scope.viewmodel = resp.data; - $rootScope.showMessage("success", "success"); - $rootScope.isBusy = false; - ctrl.viewmodel = angular.copy(ctrl.default); - if (ctrl.onUpdate) { - ctrl.onUpdate(); - } - $("#modal-files .modal-body").animate({ scrollTop: "0px" }, 500); - $scope.$apply(); + ctrl.items = []; + ctrl.init = async function () { + var resp = await apiService.getPortalMenus(); + if (resp.success && resp.data && resp.data.length) { + ctrl.items = resp.data; } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); + ctrl.items = JSON.parse($("#portal-menus").val()).items; } }; }, ], bindings: { - onUpdate: "&?", + items: "=?", }, }); -modules.component("mixDbDataValues", { +modules.component("mainSideBarDynamic", { templateUrl: - "/mix-app/views/app-portal/components/mix-db-data-values/view.html", - bindings: { - database: "=?", - request: "=", - mixDbTableName: "=?", - mixDatabaseTitle: "=?", - mixDbTableId: "=?", - relationship: "=?", - parentName: "=?", - parentId: "=?", - guidParentId: "=?", - header: "=?", - data: "=", - canDrag: "=?", - queries: "=?", - filterType: "=?", - conjunction: "=?", - selectedList: "=?", - selectSingle: "=?", - displayColumns: "=?", - onFilterList: "&?", - onApplyList: "&?", - onSendMail: "&?", - onUpdate: "&?", - onDuplicate: "&?", - onDelete: "&?", - }, + "/mix-app/views/app-portal/components/main-side-bar-dynamic/main-side-bar-dynamic.html", controller: [ "$rootScope", "$scope", - "$location", - "$routeParams", "ngAppSettings", - "RestMixDbTablePortalService", - "MixDbDataService", + "CommonService", + "TranslatorService", + "AuthService", function ( $rootScope, $scope, - $location, - $routeParams, ngAppSettings, - databaseService, - dataService + commonService, + translatorService, + authService ) { var ctrl = this; - ctrl.intShowColumn = 3; - ctrl.actions = ["Delete", "SendMail"]; - ctrl.filterTypes = ["contain", "equal"]; - ctrl.conjunctions = ["Or", "And"]; - ctrl.selectedProp = null; - ctrl.mixConfigurations = $rootScope.globalSettings; + ctrl.init = function () { + // commonService.getPermissions().then(function (response) { + // if (response && response.success) { + // ctrl.isInit = true; + // ctrl.roles = response.data; + // if (ctrl.roles.data) { + // ctrl.role = ctrl.roles.data[0]; + // } + // $rootScope.isBusy = false; + // $scope.$apply(); + // } + // }); + }; + }, + ], + bindings: { + roles: "=", + activedRole: "=", + translate: "&", + }, +}); - ctrl.$onInit = async function () { - dataService.initDbName(ctrl.mixDbTableName); +modules.component("mainSideBarItem", { + templateUrl: + "/mix-app/views/app-portal/components/main-side-bar-item/main-side-bar-item.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.translate = $rootScope.translate; + ctrl.addClass = function (obj) { + obj.currentTarget.classList.add("btn-group-lg"); + //alert(obj); + }; + ctrl.removeClass = function (obj) { + obj.currentTarget.classList.remove("btn-group-lg"); + //alert(obj); + }; + }, + ], + bindings: { + item: "=", + }, +}); - if (!ctrl.selectedList) { - ctrl.selectedList = { - action: "Delete", - data: [], - }; - } - if (!ctrl.database) { - var getDatabase = await databaseService.getByName( - ctrl.mixDbTableName - ); - if (getDatabase.success) { - ctrl.database = getDatabase.data; - } - } - ctrl.fieldNames = { - id: ctrl.database.namingConvention == "TitleCase" ? "Id" : "id", - parentId: - ctrl.database.namingConvention == "TitleCase" - ? "ParentId" - : "parent_id", - parentDatabaseName: - ctrl.database.namingConvention == "TitleCase" - ? "ParentDatabaseName" - : "parent_database_name", - childId: - ctrl.database.namingConvention == "TitleCase" - ? "ChildId" - : "child_id", - childDatabaseName: - ctrl.database.namingConvention == "TitleCase" - ? "ChildDatabaseName" - : "child_database_name", - createdDateTime: - ctrl.database.namingConvention == "TitleCase" - ? "CreatedDateTime" - : "created_date_time", - lastModified: - ctrl.database.namingConvention == "TitleCase" - ? "LastModified" - : "last_modified", - tenantId: - ctrl.database.namingConvention == "TitleCase" - ? "TenantId" - : "mix_tenant_id", - createdBy: - ctrl.database.namingConvention == "TitleCase" - ? "CreatedBy" - : "created_by", - modifiedBy: - ctrl.database.namingConvention == "TitleCase" - ? "ModifiedBy" - : "modified_by", - priority: - ctrl.database.namingConvention == "TitleCase" - ? "Priority" - : "priority", - status: - ctrl.database.namingConvention == "TitleCase" ? "Status" : "status", - isDeleted: - ctrl.database.namingConvention == "TitleCase" - ? "IsDeleted" - : "is_deleted", +modules.component("mainSideBarItemDynamic", { + templateUrl: + "/mix-app/views/app-portal/components/main-side-bar-item-dynamic/main-side-bar-item-dynamic.html", + controller: [ + "$rootScope", + function ($rootScope) { + var ctrl = this; + ctrl.translate = $rootScope.translate; + }, + ], + bindings: { + iconSize: "=", + linkStyle: "=", + itemStyle: "=", + item: "=", + }, +}); + +modules.component("mediumNews", { + templateUrl: "/mix-app/views/app-portal/components/medium-news/view.html", + controller: [ + "$rootScope", + "$http", + function ($rootScope, $http) { + var ctrl = this; + ctrl.items = []; + ctrl.init = function () { + var req = { + method: "GET", + url: + "https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/mixcore&api_key=qww481wpgat3g4iqvqss7spzrilkbekpxpjgrbof&t=" + + Math.floor(Date.now() / 1000), }; - ctrl.request.name = ctrl.mixDbTableName; - ctrl.request.sortBy = ctrl.fieldNames.id; - ctrl.request.parentName = ctrl.parentName; - ctrl.request.parentId = ctrl.parentId; - ctrl.request.relationship = ctrl.relationship; - ctrl.request.guidParentId = ctrl.guidParentId; - ctrl.request.conjunction = ctrl.conjunction; - if (!ctrl.data) { - await ctrl.loadData(); - } - ctrl.createUrl = `/admin/mix-db-data/create?mixDbTableId=${ - ctrl.database.id - }&mixDbTableName=${ctrl.database.systemName}&mixDatabaseTitle=${ - ctrl.mixDatabaseTitle - }&dataContentId=&relationship=${ctrl.relationship || ""}&parentId=${ - ctrl.parentId || ctrl.guidParentId || "" - }&parentName=${ctrl.parentName || ""}`; + ctrl.getMediumApiResult(req); }; - ctrl.toCamelCase = (txt) => { - return txt.charAt(0).toLowerCase() + txt.substr(1); + + ctrl.getMediumApiResult = async function (req) { + return $http(req).then( + function (resp) { + if (resp.status == "200") { + ctrl.items = resp.data.items; + } + }, + function (error) { + return { + success: false, + errors: [error.statusText || error.status], + }; + } + ); }; - ctrl.loadData = async function (pageIndex, pagingState = null) { - $rootScope.isBusy = true; - if (pageIndex !== undefined) { - ctrl.request.pageIndex = pageIndex; + }, + ], + bindings: {}, +}); + +modules.component("mediaFileUpload", { + templateUrl: + "/mix-app/views/app-portal/components/media-file-upload/view.html", + bindings: { + header: "=?", + accept: "=?", + src: "=", + srcUrl: "=?", + fileModel: "=?", + type: "=?", + auto: "=?", + uploadOptions: "=?", + onDelete: "&?", + onUpdate: "&?", + onInsert: "&?", + }, + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "MediaService", + function ($rootScope, $scope, ngAppSettings, mediaService) { + var ctrl = this; + ctrl.isAdmin = $rootScope.isAdmin; + var image_placeholder = "/mix-app/assets/img/image_placeholder.jpg"; + ctrl.isImage = false; + ctrl.mediaNavs = []; + ctrl.$onInit = function () { + ctrl.autoSave = ctrl.auto === "true"; + if (ctrl.src) { + ctrl.srcUrl = angular.copy(ctrl.src); } - if (pagingState) { - ctrl.request.pagingState = pagingState; + // if (!ctrl.srcUrl) { + // ctrl.srcUrl = image_placeholder; + // } + ctrl.isImage = + ctrl.srcUrl != undefined && + ctrl.srcUrl + .toLowerCase() + .match(/([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|svg|webp)/g); + ctrl.maxHeight = ctrl.maxHeight || "200px"; + ctrl.id = Math.floor(Math.random() * 100); + if (ctrl.uploadOptions) { + ctrl.w = ctrl.uploadOptions.width; + ctrl.h = ctrl.uploadOptions.height; } - dataService.initDbName(ctrl.request.mixDbTableName); - ctrl.request.queries = []; - if (ctrl.queries) { - Object.keys(ctrl.queries).forEach((e) => { - if (ctrl.queries[e]) { - ctrl.request.queries.push({ - fieldName: e, - compareOperator: ctrl.request.compareOperator, - value: ctrl.queries[e], - }); - } - }); + }; + ctrl.$doCheck = function () { + if (ctrl.src !== ctrl.srcUrl && ctrl.srcUrl != image_placeholder) { + ctrl.src = ctrl.srcUrl; + ctrl.isImage = ctrl.srcUrl + .toLowerCase() + .match(/([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|svg)/g); } - var getData = await dataService.filter(ctrl.request); - if (getData && getData.success) { - ctrl.data = getData.data; - ctrl.selectedIds = ctrl.data.items.map((m) => m.id); - $rootScope.isBusy = false; - } else { - if (getData) { - $rootScope.showErrors(getData.errors); + }.bind(ctrl); + + ctrl.selectFile = function (files) { + if (files !== undefined && files !== null && files.length > 0) { + ctrl.formFile = files[0]; + if ( + ctrl.uploadOptions && + ctrl.uploadOptions.isCrop && + $rootScope.isImage(ctrl.formFile) + ) { + ctrl.canUpload = false; + mediaService.openCroppie(files[0], ctrl, ctrl.autoSave); + } else { + ctrl.canUpload = true; + if (ctrl.autoSave) { + ctrl.uploadFile(ctrl.formFile); + } else { + ctrl.getBase64(ctrl.formFile); + } } - $rootScope.isBusy = false; } - $scope.$apply(); }; - ctrl.select = function (item) { - if (item.isSelected) { - if (ctrl.selectSingle == "true") { - ctrl.selectedList.data.items = []; - ctrl.selectedList.data.items.push(item); + + ctrl.croppieCallback = function (result) { + if (result) { + ctrl.isImage = true; + if (!ctrl.autoSave) { + ctrl.src = result; + ctrl.fileBase64 = result; } else { - var current = $rootScope.findObjectByKey( - ctrl.selectedList, - "id", - item.id + ctrl.src = result; + ctrl.srcUrl = result; + } + } else if (ctrl.formFile) { + if (ctrl.autoSave) { + ctrl.uploadFile(ctrl.formFile); + } else { + ctrl.fileModel.file = ctrl.formFile; + ctrl.getBase64(ctrl.formFile); + } + // ctrl.uploadFile(ctrl.formFile); + } + }; + + ctrl.uploadFile = async function (file) { + if (file !== null) { + $rootScope.isBusy = true; + if (file) { + ctrl.srcUrl = null; + var response = await mediaService.uploadMedia( + file, + null, + ctrl.onUploadFileProgress ); - if (!current) { - ctrl.selectedList.data.items.push(item); + if (response.success) { + ctrl.media = response.data.url; + $rootScope.isBusy = false; + ctrl.srcUrl = response.data.url; + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); } } } else { - $rootScope.removeObject(ctrl.selectedList, item.id); + return null; } }; - ctrl.selectAll = function (isSelected) { - ctrl.selectedList.data.items = []; - angular.forEach(ctrl.data.items, function (e) { - e.isSelected = isSelected; - if (isSelected) { - ctrl.selectedList.data.items.push(e.id); - } - }); - }; - ctrl.filter = function (pageIndex) { - ctrl.loadData(pageIndex); - }; - ctrl.sendMail = async function (data) { - ctrl.onSendMail({ data: data }); - }; - ctrl.apply = async function () { - ctrl.onApplyList(); + ctrl.getBase64 = function (file) { + if (file !== null) { + $rootScope.isBusy = true; + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = function () { + if (ctrl.fileModel) { + ctrl.fileModel.filename = file.name.substring( + 0, + file.name.lastIndexOf(".") + ); + ctrl.fileModel.extension = file.name.substring( + file.name.lastIndexOf(".") + ); + ctrl.fileModel.fileBase64 = reader.result; + } + ctrl.srcUrl = reader.result; + ctrl.isImage = + ctrl.srcUrl.indexOf("data:image/") >= 0 || + ctrl.srcUrl + .toLowerCase() + .match(/([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|svg)/g); + ctrl.src = reader.result; + $rootScope.isBusy = false; + $scope.$apply(); + }; + reader.onerror = function (error) { + $rootScope.isBusy = false; + $rootScope.showErrors([error]); + }; + } else { + return null; + } }; - - ctrl.duplicate = function (data) { - ctrl.onDuplicate({ data: data }); + ctrl.onUploadFileProgress = function (progress) { + ctrl.progress = progress; }; + }, + ], +}); - ctrl.update = function (data) { - let url = `/admin/mix-db-data/details?dataContentId=${ - data.id - }&mixDbTableName=${ctrl.request.mixDbTableName}&mixDbTableTitle=${ - ctrl.mixDatabaseTitle - }&guidParentId=${ctrl.guidParentId || ""}&parentId=${ - ctrl.parentId || "" - }&parentName=${ctrl.parentName || ""}`; - $location.url(url); +modules.component("mediaUpload", { + templateUrl: + "/mix-app/views/app-portal/components/media-upload/media-upload.html", + controller: [ + "$scope", + "$rootScope", + "MediaService", + "ApiService", + "CommonService", + function ($scope, $rootScope, service, apiService, commonService) { + var ctrl = this; + ctrl.default = { + title: "", + description: "", + status: "Published", + fileFolder: "Medias", + mediaFile: { + file: null, + fullPath: "", + folderName: "Media", + fileFolder: "", + fileName: "", + extension: "", + content: "", + fileBase64: "", + }, }; - - ctrl.delete = function (data) { - $rootScope.showConfirm( - ctrl, - "removeConfirmed", - [data.id], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); + ctrl.viewmodel = angular.copy(ctrl.default); + ctrl.onInsert = function (data) { + if (ctrl.onUpdate) { + ctrl.onUpdate(); + } }; - - ctrl.removeConfirmed = async function (dataContentId) { + ctrl.save = async function (data) { $rootScope.isBusy = true; - ctrl.data.items = []; - var result = await dataService.delete([dataContentId]); - if (result.success) { - if (ctrl.onDelete) { - ctrl.onDelete({ data: dataContentId }); - } - - await ctrl.loadData(); + var resp = await service.save(data); + if (resp && resp.success) { + $scope.viewmodel = resp.data; + $rootScope.showMessage("success", "success"); $rootScope.isBusy = false; + ctrl.viewmodel = angular.copy(ctrl.default); + if (ctrl.onUpdate) { + ctrl.onUpdate(); + } + $("#modal-files .modal-body").animate({ scrollTop: "0px" }, 500); $scope.$apply(); } else { - $rootScope.showErrors(result.errors); + if (resp) { + $rootScope.showErrors(resp.errors); + } $rootScope.isBusy = false; $scope.$apply(); } }; - - ctrl.filterData = function (item, attributeName) { - return $rootScope.findObjectByKey( - item.data.items, - "attributeName", - attributeName - ); - }; - - ctrl.dragStart = function (index) { - ctrl.dragStartIndex = index; - ctrl.minPriority = ctrl.data.items[0].priority; - }; - ctrl.updateOrders = function (index, items) { - if (index > ctrl.dragStartIndex) { - ctrl.data.items.splice(ctrl.dragStartIndex, 1); - } else { - ctrl.data.items.splice(ctrl.dragStartIndex + 1, 1); - } - ctrl.updateDataInfos(); - }; - ctrl.updateDataInfos = async function () { - angular.forEach(ctrl.data.items, async function (e, i) { - e.priority = ctrl.minPriority + i; - var resp = await dataService.saveFields(e.id, { - priority: e.priority, - }); - if (resp && resp.success) { - $scope.activedPage = resp.data; - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - } - }); - }; - - ctrl.view = function (item) { - var obj = { - columns: ctrl.database.columns, - item: item, - }; - $rootScope.preview("mix-db-data", obj, null, "modal-lg"); - }; }, ], + bindings: { + onUpdate: "&?", + }, }); app.component("mixMetadata", { @@ -12986,60 +12535,271 @@ app.component("mixMetadata", { ctrl.reset(); $rootScope.isBusy = false; $scope.$apply(); - } else { - $rootScope.showErrors(resp.errors); - $rootScope.isBusy = false; + } else { + $rootScope.showErrors(resp.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + } + } else { + tmp.isActived = true; + ctrl.select(tmp); + } + } + }; + + ctrl.reset = () => { + ctrl.keyword = ""; + $scope.$apply(); + }; + + ctrl.getOrCreateMetadata = async () => { + $rootScope.isBusy = true; + let dto = { + content: ctrl.keyword, + type: ctrl.metadataType, + }; + var resp = await metadataService.getOrCreateMetadata(dto); + if (resp.success) { + $rootScope.isBusy = false; + return resp.data; + } else { + $rootScope.showErrors(resp.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + + ctrl.remove = function (id) { + if ( + confirm( + "Deleted data will not able to recover, are you sure you want to delete this item?" + ) + ) { + ctrl.removeConfirmed(id); + } + }; + + ctrl.removeConfirmed = async function (id) { + $rootScope.isBusy = true; + var result = await metadataService.deleteMetadataContentAssociation(id); + if (result.success) { + await ctrl.loadMetadata(); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(result.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + }, + ], +}); + +modules.component("mixDbDataValueEditor", { + templateUrl: + "/mix-app/views/app-portal/components/mix-db-data-value-editor/view.html", + bindings: { + mixDbDataValue: "=?", + parentType: "=?", + parentId: "=?", + isShowTitle: "=?", + }, + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "$location", + "RestMixAssociationPortalService", + "RestMixDbDataPortalService", + function ( + $rootScope, + $scope, + ngAppSettings, + $location, + navService, + dataService + ) { + var ctrl = this; + ctrl.goToPath = $rootScope.goToPath; + ctrl.icons = ngAppSettings.icons; + ctrl.refData = null; + ctrl.defaultDataModel = null; + ctrl.refDataModel = { + id: null, + data: null, + }; + ctrl.refRequest = angular.copy(ngAppSettings.request); + ctrl.refRequest.pageSize = 100; + ctrl.dataTypes = $rootScope.globalSettings.dataTypes; + ctrl.previousId = null; + ctrl.$doCheck = function () { + if (ctrl.mixDbDataValue && ctrl.previousId !== ctrl.mixDbDataValue.id) { + ctrl.previousId = ctrl.mixDbDataValue.id; + ctrl.initData(); + } + }.bind(ctrl); + ctrl.$onInit = function () { + ctrl.initData(); + }; + ctrl.initData = async function () { + setTimeout(() => { + if (!ctrl.mixDbDataValue.id) { + ctrl.initDefaultValue(); + } + switch (ctrl.mixDbDataValue.dataType.toLowerCase()) { + case "datetime": + case "date": + case "time": + if (ctrl.mixDbDataValue.dateTimeValue) { + ctrl.mixDbDataValue.dateObj = new Date( + ctrl.mixDbDataValue.dateTimeValue + ); + $scope.$apply(); + } + break; + case "reference": // reference + if (ctrl.mixDbDataValue.column.referenceId && ctrl.parentId) { + ctrl.mixDbDataValue.integerValue = + ctrl.mixDbDataValue.column.referenceId; + // navService.getSingle(["default"]).then((resp) => { + // ctrl.defaultDataModel = resp; + // ctrl.defaultDataModel.mixDbTableId = + // ctrl.mixDbDataValue.column.referenceId; + // ctrl.refDataModel = angular.copy(ctrl.defaultDataModel); + // }); + // ctrl.loadRefData(); + } + break; + default: + if ( + ctrl.mixDbDataValue.column && + ctrl.mixDbDataValue.column.isEncrypt && + ctrl.mixDbDataValue.encryptValue + ) { + var encryptedData = { + key: ctrl.mixDbDataValue.encryptKey, + data: ctrl.mixDbDataValue.encryptValue, + }; + ctrl.mixDbDataValue.stringValue = + $rootScope.decrypt(encryptedData); + } + if ( + ctrl.mixDbDataValue.column && + !ctrl.mixDbDataValue.stringValue + ) { + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.column.defaultValue; $scope.$apply(); } - } - } else { - tmp.isActived = true; - ctrl.select(tmp); + break; } - } + }, 200); }; + ctrl.initDefaultValue = async function () { + switch (ctrl.mixDbDataValue.dataType) { + case "datetime": + case "date": + case "time": + if (ctrl.mixDbDataValue.column.defaultValue) { + ctrl.mixDbDataValue.dateObj = new Date( + ctrl.mixDbDataValue.column.defaultValue + ); + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.column.defaultValue; + } + break; + case "double": + if (ctrl.mixDbDataValue.column.defaultValue) { + ctrl.mixDbDataValue.doubleValue = parseFloat( + ctrl.mixDbDataValue.column.defaultValue + ); + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.column.defaultValue; + } + break; + case "boolean": + if (ctrl.mixDbDataValue.column.defaultValue) { + ctrl.mixDbDataValue.booleanValue = + ctrl.mixDbDataValue.column.defaultValue == "true"; + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.column.defaultValue; + } + break; - ctrl.reset = () => { - ctrl.keyword = ""; - $scope.$apply(); + default: + if (ctrl.mixDbDataValue.column.defaultValue) { + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.column.defaultValue; + } + break; + } }; + ctrl.updateStringValue = async function (dataType) { + switch (dataType.toLowerCase()) { + case "datetime": + case "date": + case "time": + if (ctrl.mixDbDataValue.dateObj) { + ctrl.mixDbDataValue.dateTimeValue = + ctrl.mixDbDataValue.dateObj.toISOString(); + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.dateTimeValue; + } + break; + case "double": + if (ctrl.mixDbDataValue.doubleValue) { + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.doubleValue.toString(); + } + break; + case "boolean": + if (ctrl.mixDbDataValue.booleanValue != null) { + ctrl.mixDbDataValue.stringValue = + ctrl.mixDbDataValue.booleanValue.toString(); + } + break; - ctrl.getOrCreateMetadata = async () => { - $rootScope.isBusy = true; - let dto = { - content: ctrl.keyword, - type: ctrl.metadataType, - }; - var resp = await metadataService.getOrCreateMetadata(dto); - if (resp.success) { - $rootScope.isBusy = false; - return resp.data; - } else { - $rootScope.showErrors(resp.errors); - $rootScope.isBusy = false; - $scope.$apply(); + default: + break; } }; - ctrl.remove = function (id) { - if ( - confirm( - "Deleted data will not able to recover, are you sure you want to delete this item?" - ) - ) { - ctrl.removeConfirmed(id); - } + ctrl.updateRefData = function (nav) { + ctrl.goToPath(`/admin/mix-db-data/details?dataContentId=${nav.data.id} + &mixDbTableId=${nav.data.mixDbTableId} + &parentId=${ctrl.parentId} + &parentType=${ctrl.parentType}`); + // ctrl.refDataModel = nav; + // var e = $(".pane-form-" + ctrl.mixDbDataValue.column.referenceId)[0]; + // angular.element(e).triggerHandler('click'); + // $location.url('/admin/mix-db-data/details?dataContentId='+ item.id +'&mixDbTableId=' + item.mixDbTableId+'&parentType=' + item.parentType+'&parentId=' + item.parentId); }; - ctrl.removeConfirmed = async function (id) { + ctrl.removeRefData = async function (nav) { + $rootScope.showConfirm( + ctrl, + "removeRefDataConfirmed", + [nav], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + ctrl.removeRefDataConfirmed = async function (nav) { $rootScope.isBusy = true; - var result = await metadataService.deleteMetadataContentAssociation(id); + var result = await navService.delete([ + nav.parentId, + nav.parentType, + nav.id, + ]); if (result.success) { - await ctrl.loadMetadata(); + $rootScope.removeObjectByKey(ctrl.refData, "id", nav.id); $rootScope.isBusy = false; $scope.$apply(); } else { - $rootScope.showErrors(result.errors); + $rootScope.showErros(result.errors); $rootScope.isBusy = false; $scope.$apply(); } @@ -13126,99 +12886,384 @@ modules.component("mixDatabaseNavValues", { if (index > ctrl.dragStartIndex) { ctrl.data.items.splice(ctrl.dragStartIndex, 1); } else { - ctrl.data.items.splice(ctrl.dragStartIndex + 1, 1); + ctrl.data.items.splice(ctrl.dragStartIndex + 1, 1); + } + angular.forEach(ctrl.data.items, function (e, i) { + e.priority = ctrl.minPriority + i; + navService.saveFields(e.id, { priority: e.priority }).then((resp) => { + $rootScope.isBusy = false; + $scope.$apply(); + }); + }); + }; + + ctrl.loadData = function () { + ctrl.request.mixDbTableId = ctrl.mixDbTableId || 0; + ctrl.request.mixDbTableName = ctrl.mixDbTableName || null; + ctrl.request.guidParentId = ctrl.guidParentId; + ctrl.request.intParentId = ctrl.intParentId; + ctrl.request.parentType = ctrl.parentType; + navService.getList(ctrl.request).then((resp) => { + if (resp) { + ctrl.data = resp.data; + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors("Failed"); + } + ctrl.refData = []; + $rootScope.isBusy = false; + $scope.$apply(); + } + }); + }; + ctrl.updateData = function (nav) { + $rootScope.goToPath( + `${ctrl.updateUrl}?dataContentId=${nav.childDataContent.id}&mixDbTableId=${nav.mixDbTableId}&guidParentId=${ctrl.guidParentId}&parentType=${ctrl.parentType}` + ); + // ctrl.refDataModel = nav; + // var e = $(".pane-form-" + ctrl.mixDbDataValue.column.referenceId)[0]; + // angular.element(e).triggerHandler('click'); + // $location.url('/admin/mix-db-data/details?dataContentId='+ item.id +'&mixDbTableId=' + item.mixDbTableId+'&parentType=' + item.parentType+'&parentId=' + item.parentId); + }; + ctrl.saveData = function (data) { + $rootScope.isBusy = true; + ctrl.refDataModel.data = data; + dataService.save("portal", data).then((resp) => { + if (resp.success) { + ctrl.refDataModel.id = resp.data.id; + ctrl.refDataModel.data = resp.data; + navService.save("portal", ctrl.refDataModel).then((resp) => { + if (resp.success) { + var tmp = $rootScope.findObjectByKey( + ctrl.refData, + ["parentId", "parentType", "id"], + [resp.data.parentId, resp.data.parentType, resp.data.id] + ); + if (!tmp) { + ctrl.refData.push(resp.data); + } + ctrl.refDataModel = angular.copy(ctrl.defaultDataModel); + var e = $( + ".pane-data-" + ctrl.mixDbDataValue.column.referenceId + )[0]; + angular.element(e).triggerHandler("click"); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showMessage("failed"); + $rootScope.isBusy = false; + $scope.$apply(); + } + }); + } else { + $rootScope.showMessage("failed"); + $rootScope.isBusy = false; + $scope.$apply(); + } + }); + }; + ctrl.removeData = async function (nav) { + $rootScope.showConfirm( + ctrl, + "removeDataConfirmed", + [nav], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + ctrl.removeDataConfirmed = async function (nav) { + $rootScope.isBusy = true; + var result = await navService.delete([nav.id]); + if (result.success) { + $rootScope.removeObjectByKey(ctrl.data.items, "id", nav.id); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showMessage("failed"); + $rootScope.isBusy = false; + $scope.$apply(); } - angular.forEach(ctrl.data.items, function (e, i) { - e.priority = ctrl.minPriority + i; - navService.saveFields(e.id, { priority: e.priority }).then((resp) => { - $rootScope.isBusy = false; - $scope.$apply(); - }); - }); }; + ctrl.view = function (item) { + var obj = { + columns: ctrl.columns, + item: item, + }; + $rootScope.preview("mix-db-data", obj, null, "modal-lg"); + }; + }, + ], +}); +modules.component("mixDatabaseNavData", { + templateUrl: + "/mix-app/views/app-portal/components/mix-db-data-nav-data/view.html", + bindings: { + nav: "=", + parentId: "=", + parentType: "=", + onUpdate: "&?", + onDelete: "&?", + }, + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "RestRelatedAttributeDataPortalService", + "RestMixDbDataPortalService", + function ($rootScope, $scope, ngAppSettings, navService, dataService) { + var ctrl = this; + ctrl.data = null; + ctrl.selected = null; + ctrl.navRequest = angular.copy(ngAppSettings.request); + ctrl.setRequest = angular.copy(ngAppSettings.request); + ctrl.mixConfigurations = $rootScope.globalSettings; + ctrl.$onInit = function () { + navService + .getDefault([ctrl.parentId, ctrl.parentType, "default"]) + .then((resp) => { + ctrl.defaultData = resp.data; + ctrl.defaultData.parentId = ctrl.parentId; + ctrl.defaultData.parentType = ctrl.parentType; + ctrl.selected = angular.copy(ctrl.defaultData); + ctrl.loadData(); + }); + ctrl.navRequest.parentType = ctrl.parentType; + ctrl.navRequest.parentId = ctrl.parentId; + }; + ctrl.selectPane = function (pane) {}; ctrl.loadData = function () { - ctrl.request.mixDbTableId = ctrl.mixDbTableId || 0; - ctrl.request.mixDbTableName = ctrl.mixDbTableName || null; - ctrl.request.guidParentId = ctrl.guidParentId; - ctrl.request.intParentId = ctrl.intParentId; - ctrl.request.parentType = ctrl.parentType; - navService.getList(ctrl.request).then((resp) => { + navService.getList(ctrl.navRequest).then((resp) => { if (resp) { ctrl.data = resp.data; - $rootScope.isBusy = false; $scope.$apply(); } else { if (resp) { - $rootScope.showErrors("Failed"); + $rootScope.showErrors(resp.errors); } - ctrl.refData = []; - $rootScope.isBusy = false; $scope.$apply(); } }); }; ctrl.updateData = function (nav) { - $rootScope.goToPath( - `${ctrl.updateUrl}?dataContentId=${nav.childDataContent.id}&mixDbTableId=${nav.mixDbTableId}&guidParentId=${ctrl.guidParentId}&parentType=${ctrl.parentType}` - ); - // ctrl.refDataModel = nav; - // var e = $(".pane-form-" + ctrl.mixDbDataValue.column.referenceId)[0]; - // angular.element(e).triggerHandler('click'); + ctrl.selected = nav; + var e = $(".pane-form-" + ctrl.nav.data.id)[0]; + angular.element(e).triggerHandler("click"); // $location.url('/admin/mix-db-data/details?dataContentId='+ item.id +'&mixDbTableId=' + item.mixDbTableId+'&parentType=' + item.parentType+'&parentId=' + item.parentId); }; ctrl.saveData = function (data) { $rootScope.isBusy = true; - ctrl.refDataModel.data = data; - dataService.save("portal", data).then((resp) => { + ctrl.selected.data = data; + dataService.save(data).then((resp) => { if (resp.success) { - ctrl.refDataModel.id = resp.data.id; - ctrl.refDataModel.data = resp.data; - navService.save("portal", ctrl.refDataModel).then((resp) => { + ctrl.selected.dataContentId = resp.data.id; + ctrl.selected.mixDbTableId = resp.data.mixDbTableId; + ctrl.selected.mixDbTableName = resp.data.mixDbTableName; + ctrl.selected.attributeData = resp.data; + navService.save(ctrl.selected).then((resp) => { if (resp.success) { var tmp = $rootScope.findObjectByKey( - ctrl.refData, + ctrl.data, ["parentId", "parentType", "id"], [resp.data.parentId, resp.data.parentType, resp.data.id] ); if (!tmp) { - ctrl.refData.push(resp.data); + ctrl.data.items.push(resp.data); + var e = $(".pane-data-" + ctrl.nav.data.id)[0]; + angular.element(e).triggerHandler("click"); } - ctrl.refDataModel = angular.copy(ctrl.defaultDataModel); - var e = $( - ".pane-data-" + ctrl.mixDbDataValue.column.referenceId - )[0]; - angular.element(e).triggerHandler("click"); + ctrl.selected = angular.copy(ctrl.defautData); $rootScope.isBusy = false; $scope.$apply(); } else { - $rootScope.showMessage("failed"); + $rootScope.showMessage(resp.errors); $rootScope.isBusy = false; $scope.$apply(); } }); } else { - $rootScope.showMessage("failed"); + $rootScope.showErrors(resp.errors); $rootScope.isBusy = false; $scope.$apply(); } }); }; - ctrl.removeData = async function (nav) { - $rootScope.showConfirm( - ctrl, - "removeDataConfirmed", - [nav], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); + ctrl.removeData = async function (nav) { + $rootScope.showConfirm( + ctrl, + "removeDataConfirmed", + [nav], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + ctrl.removeDataConfirmed = async function (nav) { + $rootScope.isBusy = true; + var result = await navService.delete([nav.id]); + if (result.success) { + $rootScope.removeObjectByKey(ctrl.data, "id", nav.id); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(result.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + ctrl.dragStart = function (index) { + ctrl.dragStartIndex = index; + ctrl.minPriority = ctrl.data[0].priority; + }; + ctrl.updateOrders = function (index) { + if (index > ctrl.dragStartIndex) { + ctrl.data.splice(ctrl.dragStartIndex, 1); + } else { + ctrl.data.splice(ctrl.dragStartIndex + 1, 1); + } + var arrNavs = []; + angular.forEach(ctrl.data, function (e, i) { + e.priority = ctrl.minPriority + i; + var keys = { + parentId: e.parentId, + parentType: e.parentType, + id: e.id, + }; + var properties = { + priority: e.priority, + }; + arrNavs.push({ + keys: keys, + properties: properties, + }); + }); + navService.saveProperties("portal", arrNavs).then((resp) => { + $rootScope.isBusy = false; + $scope.$apply(); + }); + }; + }, + ], +}); + +modules.component("mixDatabaseNavs", { + templateUrl: + "/mix-app/views/app-portal/components/mix-db-table-navs/view.html", + bindings: { + parentId: "=", + parentType: "=", + mixDatabaseNavs: "=?", + onUpdate: "&?", + onDelete: "&?", + }, + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "RestMixAssociationPortalService", + "RestMixDbTablePortalService", + function ($rootScope, $scope, ngAppSettings, navService, setService) { + var ctrl = this; + ctrl.mixDatabaseNavs = ctrl.mixDatabaseNavs || []; + ctrl.selected = {}; + ctrl.defaultData = null; + ctrl.navRequest = angular.copy(ngAppSettings.request); + ctrl.setRequest = angular.copy(ngAppSettings.request); + + ctrl.mixConfigurations = $rootScope.globalSettings; + ctrl.$onInit = function () { + // ctrl.setRequest.type = ctrl.parentType; + navService.getDefault().then((resp) => { + resp.parentId = ctrl.parentId; + resp.parentType = ctrl.parentType; + ctrl.defaultData = resp; + ctrl.loadData(); + }); + }; + ctrl.goToPath = $rootScope.goToPath; + ctrl.selectPane = function (pane) {}; + ctrl.loadData = async function () { + // Load attr set navs if not in input + if (!ctrl.mixDatabaseNavs) { + ctrl.navRequest.parentType = ctrl.parentType; + ctrl.navRequest.parentId = ctrl.parentId; + var resp = await navService.getList(ctrl.navRequest); + if (resp) { + angular.forEach(resp.data.items, (e) => { + e.isActived = true; + ctrl.mixDatabaseNavs.push(e); + }); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + } + } else { + angular.forEach(ctrl.mixDatabaseNavs, (e) => { + e.isActived = true; + }); + } + + var setResult = await setService.getList(ctrl.setRequest); + if (setResult) { + angular.forEach(setResult.data.items, (element) => { + var e = $rootScope.findObjectByKey( + ctrl.mixDatabaseNavs, + "mixDbTableId", + element.id + ); + if (!e) { + e = angular.copy(ctrl.defaultData); + e.status = "Published"; + e.mixDbTableId = element.id; + e.specificulture = navService.lang; + e.data = element; + e.isActived = false; + ctrl.mixDatabaseNavs.push(e); + } + }); + } else { + if (setResult) { + $rootScope.showErrors("Others Failed"); + } + } + $scope.$apply(); + }; + ctrl.change = async function (nav) { + $rootScope.isBusy = true; + var result; + if (nav.isActived) { + ctrl.active(nav); + } else { + ctrl.deactive(nav); + } + }; + + ctrl.deactive = async function (nav) { + let result = null; + if (nav.id) { + result = await navService.delete([nav.id]); + $(".pane-container-" + nav.data.id) + .parent() + .remove(); + } + if (result && result.success) { + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showMessage("failed"); + $rootScope.isBusy = false; + } }; - ctrl.removeDataConfirmed = async function (nav) { + + ctrl.active = async function (nav) { $rootScope.isBusy = true; - var result = await navService.delete([nav.id]); - if (result.success) { - $rootScope.removeObjectByKey(ctrl.data.items, "id", nav.id); + var result; + result = await navService.save(nav); + if (result && result.success) { $rootScope.isBusy = false; $scope.$apply(); } else { @@ -13227,125 +13272,247 @@ modules.component("mixDatabaseNavValues", { $scope.$apply(); } }; - ctrl.view = function (item) { - var obj = { - columns: ctrl.columns, - item: item, - }; - $rootScope.preview("mix-db-data", obj, null, "modal-lg"); + + ctrl.update = function (data) { + ctrl.onUpdate({ + data: data, + }); + }; + + ctrl.delete = function (data) { + ctrl.onDelete({ + data: data, + }); + }; + + ctrl.dragStart = function (index) { + ctrl.dragStartIndex = index; + ctrl.minPriority = ctrl.mixDatabaseNavs[0].priority; + }; + ctrl.updateOrders = function (index) { + if (index > ctrl.dragStartIndex) { + ctrl.mixDatabaseNavs.splice(ctrl.dragStartIndex, 1); + } else { + ctrl.mixDatabaseNavs.splice(ctrl.dragStartIndex + 1, 1); + } + var arrNavs = []; + angular.forEach(ctrl.mixDatabaseNavs, function (e, i) { + e.priority = ctrl.minPriority + i; + var keys = { + parentId: e.parentId, + parentType: e.parentType, + id: e.id, + }; + var properties = { + priority: e.priority, + }; + arrNavs.push({ + keys: keys, + properties: properties, + }); + }); + navService.saveProperties("portal", arrNavs).then((resp) => { + $rootScope.isBusy = false; + $scope.$apply(); + }); }; }, ], }); -modules.component("mixDatabaseNavData", { +modules.component("mixDatabaseOneToMany", { templateUrl: - "/mix-app/views/app-portal/components/mix-db-data-nav-data/view.html", + "/mix-app/views/app-portal/components/mix-db-table-one-to-many/view.html", bindings: { - nav: "=", - parentId: "=", - parentType: "=", + database: "=?", + fieldNames: "=?", + mixDbTableName: "=?", + mixDatabaseTitle: "=?", + mixDbTableId: "=?", + relationship: "=?", + parentName: "=?", + parentId: "=?", + guidParentId: "=?", + header: "=?", + data: "=?", + canDrag: "=?", + queries: "=?", + filterType: "=?", + conjunction: "=?", + selectedList: "=?", + selectSingle: "=?", + database: "=?", + onFilterList: "&?", + onApplyList: "&?", + onSendMail: "&?", onUpdate: "&?", + onDuplicate: "&?", onDelete: "&?", }, controller: [ "$rootScope", "$scope", + "$location", + "$routeParams", "ngAppSettings", - "RestRelatedAttributeDataPortalService", - "RestMixDbDataPortalService", - function ($rootScope, $scope, ngAppSettings, navService, dataService) { + "RestMixDbTablePortalService", + "MixDbDataService", + function ( + $rootScope, + $scope, + $location, + $routeParams, + ngAppSettings, + databaseService, + dataService + ) { var ctrl = this; - ctrl.data = null; - ctrl.selected = null; - ctrl.navRequest = angular.copy(ngAppSettings.request); - ctrl.setRequest = angular.copy(ngAppSettings.request); + ctrl.intShowColumn = 3; + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.actions = ["Delete", "SendMail"]; + ctrl.filterTypes = ["contain", "equal"]; + ctrl.conjunctions = ["or", "and"]; + ctrl.selectedProp = null; ctrl.mixConfigurations = $rootScope.globalSettings; - ctrl.$onInit = function () { - navService - .getDefault([ctrl.parentId, ctrl.parentType, "default"]) - .then((resp) => { - ctrl.defaultData = resp.data; - ctrl.defaultData.parentId = ctrl.parentId; - ctrl.defaultData.parentType = ctrl.parentType; - ctrl.selected = angular.copy(ctrl.defaultData); - ctrl.loadData(); - }); - ctrl.navRequest.parentType = ctrl.parentType; - ctrl.navRequest.parentId = ctrl.parentId; - }; - ctrl.selectPane = function (pane) {}; - ctrl.loadData = function () { - navService.getList(ctrl.navRequest).then((resp) => { - if (resp) { - ctrl.data = resp.data; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } + ctrl.$onInit = async function () { + dataService.initDbName(ctrl.mixDbTableName); + ctrl.request.name = ctrl.mixDbTableName; + ctrl.request.sortBy = ctrl.fieldNames.id; + ctrl.request.parentName = ctrl.parentName; + ctrl.request.parentId = ctrl.parentId; + ctrl.request.relationship = ctrl.relationship; + ctrl.request.guidParentId = ctrl.guidParentId; + if (!ctrl.selectedList) { + ctrl.selectedList = { + action: "Delete", + data: [], + }; + } + if (!ctrl.database) { + var getDatabase = await databaseService.getByName( + ctrl.mixDbTableName + ); + if (getDatabase.success) { + ctrl.database = getDatabase.data; $scope.$apply(); } - }); + } + if (!ctrl.data) { + await ctrl.loadData(); + } + ctrl.createUrl = `/admin/mix-db-data/create?mixDbTableId=${ + ctrl.database.id + }&mixDbTableName=${ctrl.database.systemName}&mixDatabaseTitle=${ + ctrl.database.displayName + }&dataContentId=&relationship=${ + ctrl.relationship || "" + }&${ctrl.getParentIdColName()}=${ + ctrl.parentId || ctrl.guidParentId || "" + }&parentName=${ctrl.parentName || ""}`; + $scope.$apply(); }; - ctrl.updateData = function (nav) { - ctrl.selected = nav; - var e = $(".pane-form-" + ctrl.nav.data.id)[0]; - angular.element(e).triggerHandler("click"); - // $location.url('/admin/mix-db-data/details?dataContentId='+ item.id +'&mixDbTableId=' + item.mixDbTableId+'&parentType=' + item.parentType+'&parentId=' + item.parentId); + ctrl.getParentIdColName = () => { + return `${ctrl.parentName}_id`; }; - ctrl.saveData = function (data) { - $rootScope.isBusy = true; - ctrl.selected.data = data; - dataService.save(data).then((resp) => { - if (resp.success) { - ctrl.selected.dataContentId = resp.data.id; - ctrl.selected.mixDbTableId = resp.data.mixDbTableId; - ctrl.selected.mixDbTableName = resp.data.mixDbTableName; - ctrl.selected.attributeData = resp.data; - navService.save(ctrl.selected).then((resp) => { - if (resp.success) { - var tmp = $rootScope.findObjectByKey( - ctrl.data, - ["parentId", "parentType", "id"], - [resp.data.parentId, resp.data.parentType, resp.data.id] - ); - if (!tmp) { - ctrl.data.items.push(resp.data); - var e = $(".pane-data-" + ctrl.nav.data.id)[0]; - angular.element(e).triggerHandler("click"); - } - ctrl.selected = angular.copy(ctrl.defautData); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showMessage(resp.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }); + ctrl.toCamelCase = (txt) => { + return txt.charAt(0).toLowerCase() + txt.substr(1); + }; + ctrl.loadData = async function () { + dataService.initDbName(ctrl.mixDbTableName); + ctrl.request.queries = []; + if (ctrl.queries) { + Object.keys(ctrl.queries).forEach((e) => { + if (ctrl.queries[e]) { + ctrl.request.queries.push({ + fieldName: e, + value: ctrl.queries[e], + }); + } + }); + } + var getData = await dataService.filterNestedData(ctrl.request); + ctrl.data = getData.data; + if (ctrl.request.relationship == "ManyToMany") { + ctrl.selectedIds = ctrl.data.items.map((m) => ({ + id: m.id, + dataId: m.data.id, + })); + } + $scope.$apply(); + }; + ctrl.select = function (item) { + if (item.isSelected) { + if (ctrl.selectSingle == "true") { + ctrl.selectedList.data.items = []; + ctrl.selectedList.data.items.push(item); } else { - $rootScope.showErrors(resp.errors); - $rootScope.isBusy = false; - $scope.$apply(); + var current = $rootScope.findObjectByKey( + ctrl.selectedList, + "id", + item.id + ); + if (!current) { + ctrl.selectedList.data.items.push(item); + } + } + } else { + $rootScope.removeObject(ctrl.selectedList, item.id); + } + }; + ctrl.selectAll = function (isSelected) { + ctrl.selectedList.data.items = []; + angular.forEach(ctrl.data.items, function (e) { + e.isSelected = isSelected; + if (isSelected) { + ctrl.selectedList.data.items.push(e.id); } }); }; - ctrl.removeData = async function (nav) { + ctrl.filter = function () { + ctrl.data.items = []; + ctrl.loadData(); + }; + ctrl.sendMail = async function (data) { + ctrl.onSendMail({ data: data }); + }; + ctrl.apply = async function () { + ctrl.onApplyList(); + }; + + ctrl.duplicate = function (data) { + ctrl.onDuplicate({ data: data }); + }; + + ctrl.update = function (item) { + let url = `/admin/mix-db-data/details?dataContentId=${ + item.id + }&mixDbTableName=${ctrl.mixDbTableName}&mixDatabaseTitle=${ + ctrl.mixDatabaseTitle + }&guidParentId=${ctrl.guidParentId || ""}&parentId=${ + ctrl.parentId || "" + }&parentName=${ctrl.parentName || ""}`; + $location.url(url); + }; + + ctrl.delete = function (data) { $rootScope.showConfirm( ctrl, - "removeDataConfirmed", - [nav], + "removeConfirmed", + [data.id], null, "Remove", "Deleted data will not able to recover, are you sure you want to delete this item?" ); }; - ctrl.removeDataConfirmed = async function (nav) { + + ctrl.removeConfirmed = async function (dataContentId) { $rootScope.isBusy = true; - var result = await navService.delete([nav.id]); + var result = await dataService.delete([dataContentId]); if (result.success) { - $rootScope.removeObjectByKey(ctrl.data, "id", nav.id); + if (ctrl.onDelete) { + ctrl.onDelete({ data: dataContentId }); + } + await ctrl.loadData(); $rootScope.isBusy = false; $scope.$apply(); } else { @@ -13354,207 +13521,354 @@ modules.component("mixDatabaseNavData", { $scope.$apply(); } }; + + ctrl.filterData = function (item, attributeName) { + return $rootScope.findObjectByKey( + item.data.items, + "attributeName", + attributeName + ); + }; + ctrl.dragStart = function (index) { ctrl.dragStartIndex = index; - ctrl.minPriority = ctrl.data[0].priority; + ctrl.minPriority = ctrl.data.items[0].priority; }; - ctrl.updateOrders = function (index) { + ctrl.updateOrders = function (index, items) { if (index > ctrl.dragStartIndex) { - ctrl.data.splice(ctrl.dragStartIndex, 1); + ctrl.data.items.splice(ctrl.dragStartIndex, 1); } else { - ctrl.data.splice(ctrl.dragStartIndex + 1, 1); + ctrl.data.items.splice(ctrl.dragStartIndex + 1, 1); } - var arrNavs = []; - angular.forEach(ctrl.data, function (e, i) { + ctrl.updateDataInfos(); + }; + ctrl.updateDataInfos = async function () { + angular.forEach(ctrl.data.items, async function (e, i) { e.priority = ctrl.minPriority + i; - var keys = { - parentId: e.parentId, - parentType: e.parentType, - id: e.id, - }; - var properties = { + var resp = await dataService.saveFields(e.id, { priority: e.priority, - }; - arrNavs.push({ - keys: keys, - properties: properties, }); + if (resp && resp.success) { + $scope.activedPage = resp.data; + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + } }); - navService.saveProperties("portal", arrNavs).then((resp) => { - $rootScope.isBusy = false; - $scope.$apply(); - }); + }; + + ctrl.view = function (item) { + var obj = { + columns: ctrl.database.columns, + item: item, + }; + $rootScope.preview("mix-db-data", obj, null, "modal-lg"); }; }, ], }); -modules.component("mixDatabaseNavs", { +modules.component("mixDbDataValues", { templateUrl: - "/mix-app/views/app-portal/components/mix-db-table-navs/view.html", + "/mix-app/views/app-portal/components/mix-db-data-values/view.html", bindings: { - parentId: "=", - parentType: "=", - mixDatabaseNavs: "=?", + database: "=?", + request: "=", + mixDbTableName: "=?", + mixDatabaseTitle: "=?", + mixDbTableId: "=?", + relationship: "=?", + parentName: "=?", + parentId: "=?", + guidParentId: "=?", + header: "=?", + data: "=", + canDrag: "=?", + queries: "=?", + filterType: "=?", + conjunction: "=?", + selectedList: "=?", + selectSingle: "=?", + displayColumns: "=?", + onFilterList: "&?", + onApplyList: "&?", + onSendMail: "&?", onUpdate: "&?", + onDuplicate: "&?", onDelete: "&?", }, controller: [ "$rootScope", "$scope", + "$location", + "$routeParams", "ngAppSettings", - "RestMixAssociationPortalService", "RestMixDbTablePortalService", - function ($rootScope, $scope, ngAppSettings, navService, setService) { + "MixDbDataService", + function ( + $rootScope, + $scope, + $location, + $routeParams, + ngAppSettings, + databaseService, + dataService + ) { var ctrl = this; - ctrl.mixDatabaseNavs = ctrl.mixDatabaseNavs || []; - ctrl.selected = {}; - ctrl.defaultData = null; - ctrl.navRequest = angular.copy(ngAppSettings.request); - ctrl.setRequest = angular.copy(ngAppSettings.request); - + ctrl.intShowColumn = 3; + ctrl.actions = ["Delete", "SendMail"]; + ctrl.filterTypes = ["contain", "equal"]; + ctrl.conjunctions = ["Or", "And"]; + ctrl.selectedProp = null; ctrl.mixConfigurations = $rootScope.globalSettings; - ctrl.$onInit = function () { - // ctrl.setRequest.type = ctrl.parentType; - navService.getDefault().then((resp) => { - resp.parentId = ctrl.parentId; - resp.parentType = ctrl.parentType; - ctrl.defaultData = resp; - ctrl.loadData(); - }); + + ctrl.$onInit = async function () { + dataService.initDbName(ctrl.mixDbTableName); + + if (!ctrl.selectedList) { + ctrl.selectedList = { + action: "Delete", + data: [], + }; + } + if (!ctrl.database) { + var getDatabase = await databaseService.getByName( + ctrl.mixDbTableName + ); + if (getDatabase.success) { + ctrl.database = getDatabase.data; + } + } + ctrl.fieldNames = { + id: ctrl.database.namingConvention == "TitleCase" ? "Id" : "id", + parentId: + ctrl.database.namingConvention == "TitleCase" + ? "ParentId" + : "parent_id", + parentDatabaseName: + ctrl.database.namingConvention == "TitleCase" + ? "ParentDatabaseName" + : "parent_database_name", + childId: + ctrl.database.namingConvention == "TitleCase" + ? "ChildId" + : "child_id", + childDatabaseName: + ctrl.database.namingConvention == "TitleCase" + ? "ChildDatabaseName" + : "child_database_name", + createdDateTime: + ctrl.database.namingConvention == "TitleCase" + ? "CreatedDateTime" + : "created_date_time", + lastModified: + ctrl.database.namingConvention == "TitleCase" + ? "LastModified" + : "last_modified", + tenantId: + ctrl.database.namingConvention == "TitleCase" + ? "TenantId" + : "mix_tenant_id", + createdBy: + ctrl.database.namingConvention == "TitleCase" + ? "CreatedBy" + : "created_by", + modifiedBy: + ctrl.database.namingConvention == "TitleCase" + ? "ModifiedBy" + : "modified_by", + priority: + ctrl.database.namingConvention == "TitleCase" + ? "Priority" + : "priority", + status: + ctrl.database.namingConvention == "TitleCase" ? "Status" : "status", + isDeleted: + ctrl.database.namingConvention == "TitleCase" + ? "IsDeleted" + : "is_deleted", + }; + ctrl.request.name = ctrl.mixDbTableName; + ctrl.request.sortBy = ctrl.fieldNames.id; + ctrl.request.parentName = ctrl.parentName; + ctrl.request.parentId = ctrl.parentId; + ctrl.request.relationship = ctrl.relationship; + ctrl.request.guidParentId = ctrl.guidParentId; + ctrl.request.conjunction = ctrl.conjunction; + if (!ctrl.data) { + await ctrl.loadData(); + } + ctrl.createUrl = `/admin/mix-db-data/create?mixDbTableId=${ + ctrl.database.id + }&mixDbTableName=${ctrl.database.systemName}&mixDatabaseTitle=${ + ctrl.mixDatabaseTitle + }&dataContentId=&relationship=${ctrl.relationship || ""}&parentId=${ + ctrl.parentId || ctrl.guidParentId || "" + }&parentName=${ctrl.parentName || ""}`; }; - ctrl.goToPath = $rootScope.goToPath; - ctrl.selectPane = function (pane) {}; - ctrl.loadData = async function () { - // Load attr set navs if not in input - if (!ctrl.mixDatabaseNavs) { - ctrl.navRequest.parentType = ctrl.parentType; - ctrl.navRequest.parentId = ctrl.parentId; - var resp = await navService.getList(ctrl.navRequest); - if (resp) { - angular.forEach(resp.data.items, (e) => { - e.isActived = true; - ctrl.mixDatabaseNavs.push(e); - }); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - } - } else { - angular.forEach(ctrl.mixDatabaseNavs, (e) => { - e.isActived = true; - }); + ctrl.toCamelCase = (txt) => { + return txt.charAt(0).toLowerCase() + txt.substr(1); + }; + ctrl.loadData = async function (pageIndex, pagingState = null) { + $rootScope.isBusy = true; + if (pageIndex !== undefined) { + ctrl.request.pageIndex = pageIndex; } - - var setResult = await setService.getList(ctrl.setRequest); - if (setResult) { - angular.forEach(setResult.data.items, (element) => { - var e = $rootScope.findObjectByKey( - ctrl.mixDatabaseNavs, - "mixDbTableId", - element.id - ); - if (!e) { - e = angular.copy(ctrl.defaultData); - e.status = "Published"; - e.mixDbTableId = element.id; - e.specificulture = navService.lang; - e.data = element; - e.isActived = false; - ctrl.mixDatabaseNavs.push(e); + if (pagingState) { + ctrl.request.pagingState = pagingState; + } + dataService.initDbName(ctrl.request.mixDbTableName); + ctrl.request.queries = []; + if (ctrl.queries) { + Object.keys(ctrl.queries).forEach((e) => { + if (ctrl.queries[e]) { + ctrl.request.queries.push({ + fieldName: e, + compareOperator: ctrl.request.compareOperator, + value: ctrl.queries[e], + }); } }); + } + var getData = await dataService.filter(ctrl.request); + if (getData && getData.success) { + ctrl.data = getData.data; + ctrl.selectedIds = ctrl.data.items.map((m) => m.id); + $rootScope.isBusy = false; } else { - if (setResult) { - $rootScope.showErrors("Others Failed"); + if (getData) { + $rootScope.showErrors(getData.errors); } + $rootScope.isBusy = false; } $scope.$apply(); }; - ctrl.change = async function (nav) { - $rootScope.isBusy = true; - var result; - if (nav.isActived) { - ctrl.active(nav); + ctrl.select = function (item) { + if (item.isSelected) { + if (ctrl.selectSingle == "true") { + ctrl.selectedList.data.items = []; + ctrl.selectedList.data.items.push(item); + } else { + var current = $rootScope.findObjectByKey( + ctrl.selectedList, + "id", + item.id + ); + if (!current) { + ctrl.selectedList.data.items.push(item); + } + } } else { - ctrl.deactive(nav); + $rootScope.removeObject(ctrl.selectedList, item.id); } }; + ctrl.selectAll = function (isSelected) { + ctrl.selectedList.data.items = []; + angular.forEach(ctrl.data.items, function (e) { + e.isSelected = isSelected; + if (isSelected) { + ctrl.selectedList.data.items.push(e.id); + } + }); + }; + ctrl.filter = function (pageIndex) { + ctrl.loadData(pageIndex); + }; + ctrl.sendMail = async function (data) { + ctrl.onSendMail({ data: data }); + }; + ctrl.apply = async function () { + ctrl.onApplyList(); + }; - ctrl.deactive = async function (nav) { - let result = null; - if (nav.id) { - result = await navService.delete([nav.id]); - $(".pane-container-" + nav.data.id) - .parent() - .remove(); - } - if (result && result.success) { - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showMessage("failed"); - $rootScope.isBusy = false; - } + ctrl.duplicate = function (data) { + ctrl.onDuplicate({ data: data }); }; - ctrl.active = async function (nav) { + ctrl.update = function (data) { + let url = `/admin/mix-db-data/details?dataContentId=${ + data.id + }&mixDbTableName=${ctrl.request.mixDbTableName}&mixDbTableTitle=${ + ctrl.mixDatabaseTitle + }&guidParentId=${ctrl.guidParentId || ""}&parentId=${ + ctrl.parentId || "" + }&parentName=${ctrl.parentName || ""}`; + $location.url(url); + }; + + ctrl.delete = function (data) { + $rootScope.showConfirm( + ctrl, + "removeConfirmed", + [data.id], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + + ctrl.removeConfirmed = async function (dataContentId) { $rootScope.isBusy = true; - var result; - result = await navService.save(nav); - if (result && result.success) { + ctrl.data.items = []; + var result = await dataService.delete([dataContentId]); + if (result.success) { + if (ctrl.onDelete) { + ctrl.onDelete({ data: dataContentId }); + } + + await ctrl.loadData(); $rootScope.isBusy = false; $scope.$apply(); } else { - $rootScope.showMessage("failed"); + $rootScope.showErrors(result.errors); $rootScope.isBusy = false; $scope.$apply(); } }; - ctrl.update = function (data) { - ctrl.onUpdate({ - data: data, - }); - }; - - ctrl.delete = function (data) { - ctrl.onDelete({ - data: data, - }); + ctrl.filterData = function (item, attributeName) { + return $rootScope.findObjectByKey( + item.data.items, + "attributeName", + attributeName + ); }; ctrl.dragStart = function (index) { ctrl.dragStartIndex = index; - ctrl.minPriority = ctrl.mixDatabaseNavs[0].priority; + ctrl.minPriority = ctrl.data.items[0].priority; }; - ctrl.updateOrders = function (index) { + ctrl.updateOrders = function (index, items) { if (index > ctrl.dragStartIndex) { - ctrl.mixDatabaseNavs.splice(ctrl.dragStartIndex, 1); + ctrl.data.items.splice(ctrl.dragStartIndex, 1); } else { - ctrl.mixDatabaseNavs.splice(ctrl.dragStartIndex + 1, 1); + ctrl.data.items.splice(ctrl.dragStartIndex + 1, 1); } - var arrNavs = []; - angular.forEach(ctrl.mixDatabaseNavs, function (e, i) { + ctrl.updateDataInfos(); + }; + ctrl.updateDataInfos = async function () { + angular.forEach(ctrl.data.items, async function (e, i) { e.priority = ctrl.minPriority + i; - var keys = { - parentId: e.parentId, - parentType: e.parentType, - id: e.id, - }; - var properties = { + var resp = await dataService.saveFields(e.id, { priority: e.priority, - }; - arrNavs.push({ - keys: keys, - properties: properties, }); + if (resp && resp.success) { + $scope.activedPage = resp.data; + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + } }); - navService.saveProperties("portal", arrNavs).then((resp) => { - $rootScope.isBusy = false; - $scope.$apply(); - }); + }; + + ctrl.view = function (item) { + var obj = { + columns: ctrl.database.columns, + item: item, + }; + $rootScope.preview("mix-db-data", obj, null, "modal-lg"); }; }, ], @@ -13733,250 +14047,399 @@ modules.component("mixDbDataFilter", { ], }); -modules.component("mixDatabaseOneToMany", { +modules.component("mixDbDataForm", { templateUrl: - "/mix-app/views/app-portal/components/mix-db-table-one-to-many/view.html", + "/mix-app/views/app-portal/components/mix-db-data-form/view.html", bindings: { database: "=?", - fieldNames: "=?", + mixDbTableId: "=?", mixDbTableName: "=?", mixDatabaseTitle: "=?", - mixDbTableId: "=?", - relationship: "=?", + mixDatabaseType: "=?", + parentId: "=?", + parentType: "=?", // MixContentType parentName: "=?", - parentId: "=?", + postId: "=?", + pageId: "=?", + moduleId: "=?", + columns: "=?", + references: "=?", + mixDataContentId: "=?", + mixDataContent: "=?", + intParentId: "=?", guidParentId: "=?", - header: "=?", - data: "=?", - canDrag: "=?", - queries: "=?", - filterType: "=?", - conjunction: "=?", - selectedList: "=?", - selectSingle: "=?", - database: "=?", - onFilterList: "&?", - onApplyList: "&?", - onSendMail: "&?", - onUpdate: "&?", - onDuplicate: "&?", - onDelete: "&?", + defaultId: "=", + backUrl: "=?", + level: "=?", + hideAction: "=?", + hiddenColumns: "=?", + onSave: "&?", + onSaveSuccess: "&?", }, controller: [ "$rootScope", "$scope", - "$location", "$routeParams", - "ngAppSettings", + "$location", + "RestMixAssociationPortalService", "RestMixDbTablePortalService", "MixDbDataService", + "AuthService", function ( $rootScope, $scope, - $location, $routeParams, - ngAppSettings, + $location, + associationService, databaseService, - dataService + service, + authService ) { var ctrl = this; - ctrl.intShowColumn = 3; - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.actions = ["Delete", "SendMail"]; - ctrl.filterTypes = ["contain", "equal"]; - ctrl.conjunctions = ["or", "and"]; + var endpoints = JSON.parse(localStorage.getItem("ls.endpoints") || "{}"); + BaseHub.call(this, ctrl, endpoints.Messenger); + + ctrl.isBusy = true; + ctrl.attributes = []; + ctrl.isInRole = $rootScope.isInRole; + ctrl.defaultData = null; ctrl.selectedProp = null; ctrl.mixConfigurations = $rootScope.globalSettings; - ctrl.$onInit = async function () { - dataService.initDbName(ctrl.mixDbTableName); - ctrl.request.name = ctrl.mixDbTableName; - ctrl.request.sortBy = ctrl.fieldNames.id; - ctrl.request.parentName = ctrl.parentName; - ctrl.request.parentId = ctrl.parentId; - ctrl.request.relationship = ctrl.relationship; - ctrl.request.guidParentId = ctrl.guidParentId; - if (!ctrl.selectedList) { - ctrl.selectedList = { - action: "Delete", - data: [], - }; - } + + ctrl.init = async function () { + ctrl.level = ctrl.level || 0; + ctrl.canSave = ctrl.onSave != undefined; if (!ctrl.database) { - var getDatabase = await databaseService.getByName( + let getDatabase = await databaseService.getByName( ctrl.mixDbTableName ); - if (getDatabase.success) { - ctrl.database = getDatabase.data; - $scope.$apply(); + ctrl.database = getDatabase.data; + } + ctrl.fieldNames = { + id: ctrl.database.namingConvention == "TitleCase" ? "Id" : "id", + parentId: + ctrl.database.namingConvention == "TitleCase" + ? "ParentId" + : "parent_id", + parentDatabaseName: + ctrl.database.namingConvention == "TitleCase" + ? "ParentDatabaseName" + : "parent_database_name", + childId: + ctrl.database.namingConvention == "TitleCase" + ? "ChildId" + : "child_id", + childDatabaseName: + ctrl.database.namingConvention == "TitleCase" + ? "ChildDatabaseName" + : "child_database_name", + createdDateTime: + ctrl.database.namingConvention == "TitleCase" + ? "CreatedDateTime" + : "created_date_time", + lastModified: + ctrl.database.namingConvention == "TitleCase" + ? "LastModified" + : "last_modified", + tenantId: + ctrl.database.namingConvention == "TitleCase" + ? "TenantId" + : "mix_tenant_id", + createdBy: + ctrl.database.namingConvention == "TitleCase" + ? "CreatedBy" + : "created_by", + modifiedBy: + ctrl.database.namingConvention == "TitleCase" + ? "ModifiedBy" + : "modified_by", + priority: + ctrl.database.namingConvention == "TitleCase" + ? "Priority" + : "priority", + status: + ctrl.database.namingConvention == "TitleCase" ? "Status" : "status", + isDeleted: + ctrl.database.namingConvention == "TitleCase" + ? "IsDeleted" + : "is_deleted", + }; + await service.initDbName(ctrl.mixDbTableName); + await ctrl.loadData(); + ctrl.connectHub(); + ctrl.isBusy = false; + $scope.$apply(); + }; + ctrl.connectHub = () => { + ctrl.startConnection( + "mixDbHub", + authService.authentication.accessToken, + (err) => { + if ( + authService.authentication.refreshToken && + err.message.indexOf("401") >= 0 + ) { + authService.refreshToken().then(async () => { + $scope.startConnection( + "mixDbHub", + authService.authentication.accessToken + ); + }); + } + } + ); + }; + ctrl.onConnected = () => { + ctrl.joinRooms(); + }; + ctrl.joinRooms = function () { + ctrl.connection.invoke("JoinRooms", [ctrl.mixDbTableName]); + }; + ctrl.hubCreateData = function () { + let msg = { + connectionId: ctrl.hubRequest.from.connectionId, + mixDbName: ctrl.mixDbTableName, + requestedBy: "", + body: ctrl.mixDataContent, + }; + if (!ctrl.mixDataContent.id) { + ctrl.connection.invoke("CreateData", JSON.stringify(msg)); + } else { + ctrl.connection.invoke("UpdateData", JSON.stringify(msg)); + } + $rootScope.showMessage("Request Sent", "success"); + }; + ctrl.receiveMessage = function (msg) { + switch (msg.action) { + case "MyConnection": + ctrl.hubRequest.from = msg.data; + break; + case "NewMessage": + if (msg.type == "Success") { + $rootScope.showMessage(msg.title, "success"); + ctrl.back(); + } + if (msg.type == "Error") { + $rootScope.showErrors([msg.title]); + } + break; + } + }; + ctrl.back = function () { + if (ctrl.backUrl) { + $location.url(ctrl.backUrl); + } else { + window.history.back(); + } + }; + ctrl.translate = (keyword) => { + return $rootScope.translate(keyword); + }; + ctrl.loadData = async function () { + /* + If input is data id => load ctrl.mixDataContent from service and handle it independently + */ + ctrl.isBusy = true; + if (!ctrl.mixDataContent && ctrl.mixDataContentId) { + await ctrl.loadExistingData(); + } + if ( + !ctrl.mixDataContent && + (ctrl.mixDbTableName || ctrl.mixDbTableId) && + !ctrl.defaultData + ) { + ctrl.mixDataContent = {}; + if (ctrl.parentId) { + if (ctrl.database.rela) + ctrl.mixDataContent[ctrl.fieldNames.parentId] = ctrl.parentId; + } + // await ctrl.loadDefaultModel(); + ctrl.isBusy = false; + } + if ($routeParams.parentId) { + var relationship = $routeParams.relationship || "OneToMany"; + if (relationship == "OneToMany") { + if (ctrl.database.namingConvention == "SnakeCase") { + ctrl.mixDataContent[`${$routeParams.parentName}_id`] = + $routeParams.parentId; + } else { + ctrl.mixDataContent[`${$routeParams.parentName}Id`] = + $routeParams.parentId; + } + } else { + ctrl.mixDataContent[ctrl.fieldNames.parentId] = + $routeParams.parentId; + ctrl.mixDataContent[ctrl.fieldNames.parentDatabaseName] = + $routeParams.parentName; + ctrl.mixDataContent[ctrl.fieldNames.childDatabaseName] = + ctrl.mixDbTableName; + } + } + $scope.$apply(); + // TODO: refactor db relationship + // if ($routeParams.parentId && $routeParams.parentName) { + // var getAssociation = await associationService.getAssociation( + // $routeParams.parentName, + // ctrl.mixDbTableName, + // $routeParams.parentId, + // ctrl.mixDataContent.id + // ); + // if (getAssociation.success) { + // ctrl.association = getAssociation.data; + // } else { + // ctrl.association = { + // parentId: $routeParams.parentId, + // parentDatabaseName: $routeParams.parentName, + // childDatabaseName: ctrl.mixDbTableName, + // }; + // } + // var parentIdNameFieldName = `${$routeParams.parentName + // .charAt(0) + // .toLowerCase()}${ + // $routeParams.parentName.slice(1) || $routeParams.parentName + // }Id`; + // if (!ctrl.mixDataContent[parentIdNameFieldName]) { + // ctrl.mixDataContent[parentIdNameFieldName] = $routeParams.parentId; + // } + // } + }; + ctrl.loadExistingData = async function () { + service.initDbName(ctrl.mixDbTableName); + var getData = await service.getSingle([ctrl.mixDataContentId], { + loadNestedData: true, + }); + ctrl.mixDataContent = getData.data; + if (ctrl.mixDataContent) { + ctrl.mixDatabaseTitle = + ctrl.mixDatabaseTitle || + $routeParams.mixDatabaseTitle || + ctrl.mixDbTableName; + ctrl.backUrl = + ctrl.backUrl ?? + `/admin/mix-db-data/list?mixDbTableId=${ctrl.mixDataContent.mixDbTableId}&mixDbTableName=${ctrl.mixDbTableName}&mixDatabaseTitle=${ctrl.mixDatabaseTitle}`; + // await ctrl.loadDefaultModel(); + ctrl.isBusy = false; + } else { + if (getData) { + $rootScope.showErrors(getData.errors); } + ctrl.isBusy = false; } - if (!ctrl.data) { - await ctrl.loadData(); - } - ctrl.createUrl = `/admin/mix-db-data/create?mixDbTableId=${ - ctrl.database.id - }&mixDbTableName=${ctrl.database.systemName}&mixDatabaseTitle=${ - ctrl.database.displayName - }&dataContentId=&relationship=${ - ctrl.relationship || "" - }&${ctrl.getParentIdColName()}=${ - ctrl.parentId || ctrl.guidParentId || "" - }&parentName=${ctrl.parentName || ""}`; $scope.$apply(); }; - ctrl.getParentIdColName = () => { - return `${ctrl.parentName}_id`; - }; - ctrl.toCamelCase = (txt) => { - return txt.charAt(0).toLowerCase() + txt.substr(1); + ctrl.reload = async function () { + ctrl.mixDataContent = angular.copy(ctrl.defaultData); }; - ctrl.loadData = async function () { - dataService.initDbName(ctrl.mixDbTableName); - ctrl.request.queries = []; - if (ctrl.queries) { - Object.keys(ctrl.queries).forEach((e) => { - if (ctrl.queries[e]) { - ctrl.request.queries.push({ - fieldName: e, - value: ctrl.queries[e], - }); - } - }); - } - var getData = await dataService.filterNestedData(ctrl.request); - ctrl.data = getData.data; - if (ctrl.request.relationship == "ManyToMany") { - ctrl.selectedIds = ctrl.data.items.map((m) => ({ - id: m.id, - dataId: m.data.id, - })); + ctrl.loadSelected = function () { + if (ctrl.selectedList.data.length) { + ctrl.mixDataContent = ctrl.selectedList.data[0]; + ctrl.mixDataContent.mixDbTableId = ctrl.mixDbTableId; + ctrl.mixDataContent.mixDbTableName = ctrl.mixDbTableName; + if (ctrl.parentId) { + ctrl.mixDataContent[ctrl.fieldNames.parentId] = ctrl.parentId; + } + if (ctrl.guidParentId) { + ctrl.mixDataContent[ctrl.fieldNames.parentId] = ctrl.guidParentId; + } + ctrl.mixDataContent.parentType = ctrl.parentType; } - $scope.$apply(); }; - ctrl.select = function (item) { - if (item.isSelected) { - if (ctrl.selectSingle == "true") { - ctrl.selectedList.data.items = []; - ctrl.selectedList.data.items.push(item); + ctrl.submit = async function () { + if (ctrl.validate()) { + if (ctrl.onSave) { + ctrl.onSave({ data: ctrl.mixDataContent }); } else { - var current = $rootScope.findObjectByKey( - ctrl.selectedList, - "id", - item.id - ); - if (!current) { - ctrl.selectedList.data.items.push(item); + ctrl.isBusy = true; + service.initDbName(ctrl.mixDbTableName); + var saveResult = await service.save(ctrl.mixDataContent); + if (saveResult.success) { + ctrl.mixDataContent = saveResult.data; + if (ctrl.association) { + let result = await ctrl.saveAssociation(ctrl.mixDataContent); + if (result.success) { + ctrl.isBusy = false; + $rootScope.showMessage("success"); + $scope.$apply(); + } else { + ctrl.isBusy = false; + $rootScope.showErrors(result.errors); + $scope.$apply(); + } + } else { + if (ctrl.onSaveSuccess) { + ctrl.onSaveSuccess({ data: ctrl.mixDataContent }); + } + ctrl.isBusy = false; + $rootScope.showMessage("success"); + $scope.$apply(); + } + } else { + ctrl.isBusy = false; + if (saveResult) { + $rootScope.showErrors(saveResult.errors); + } + $scope.$apply(); } } - } else { - $rootScope.removeObject(ctrl.selectedList, item.id); } }; - ctrl.selectAll = function (isSelected) { - ctrl.selectedList.data.items = []; - angular.forEach(ctrl.data.items, function (e) { - e.isSelected = isSelected; - if (isSelected) { - ctrl.selectedList.data.items.push(e.id); - } - }); - }; - ctrl.filter = function () { - ctrl.data.items = []; - ctrl.loadData(); - }; - ctrl.sendMail = async function (data) { - ctrl.onSendMail({ data: data }); - }; - ctrl.apply = async function () { - ctrl.onApplyList(); - }; - - ctrl.duplicate = function (data) { - ctrl.onDuplicate({ data: data }); - }; - - ctrl.update = function (item) { - let url = `/admin/mix-db-data/details?dataContentId=${ - item.id - }&mixDbTableName=${ctrl.mixDbTableName}&mixDatabaseTitle=${ - ctrl.mixDatabaseTitle - }&guidParentId=${ctrl.guidParentId || ""}&parentId=${ - ctrl.parentId || "" - }&parentName=${ctrl.parentName || ""}`; - $location.url(url); - }; - - ctrl.delete = function (data) { - $rootScope.showConfirm( - ctrl, - "removeConfirmed", - [data.id], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); + ctrl.saveAssociation = async function (data) { + ctrl.association.childId = data.id; + return await associationService.save(ctrl.association); }; - - ctrl.removeConfirmed = async function (dataContentId) { - $rootScope.isBusy = true; - var result = await dataService.delete([dataContentId]); - if (result.success) { - if (ctrl.onDelete) { - ctrl.onDelete({ data: dataContentId }); + ctrl.validate = function () { + var isValid = true; + ctrl.errors = []; + angular.forEach(ctrl.columns, function (column) { + if (column.regex) { + var regex = RegExp(column.regex, "g"); + isValid = regex.test(ctrl.mixDataContent.data[column.name]); + if (!isValid) { + ctrl.errors.push(`${column.name} is not match Regex`); + } } - await ctrl.loadData(); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(result.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - - ctrl.filterData = function (item, attributeName) { - return $rootScope.findObjectByKey( - item.data.items, - "attributeName", - attributeName - ); + if (!isValid) { + $rootScope.showErrors(ctrl.errors); + } + if (isValid && column.isEncrypt) { + ctrl.mixDataContent.data[column.name] = $rootScope.encrypt( + ctrl.mixDataContent.data[column.name] + ); + } + }); + return isValid; }; - - ctrl.dragStart = function (index) { - ctrl.dragStartIndex = index; - ctrl.minPriority = ctrl.data.items[0].priority; + ctrl.showContentFilter = function ($event) { + $rootScope.showContentFilter(ctrl.loadSelectedLink); }; - ctrl.updateOrders = function (index, items) { - if (index > ctrl.dragStartIndex) { - ctrl.data.items.splice(ctrl.dragStartIndex, 1); - } else { - ctrl.data.items.splice(ctrl.dragStartIndex + 1, 1); + ctrl.loadSelectedLink = function (data, type) { + if (data) { + ctrl.mixDataContent.data.target_id = data.id; + ctrl.mixDataContent.data.title = data.title; + ctrl.mixDataContent.data.type = type; + ctrl.mixDataContent.data.uri = data.detailUrl; } - ctrl.updateDataInfos(); }; - ctrl.updateDataInfos = async function () { - angular.forEach(ctrl.data.items, async function (e, i) { - e.priority = ctrl.minPriority + i; - var resp = await dataService.saveFields(e.id, { - priority: e.priority, - }); - if (resp && resp.success) { - $scope.activedPage = resp.data; - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } + ctrl.filterData = function (attributeName) { + if (ctrl.mixDataContent) { + var attr = $rootScope.findObjectByKey( + ctrl.mixDataContent.data, + "mixDatabaseColumnName", + attributeName + ); + if (!attr) { + attr = angular.copy( + $rootScope.findObjectByKey( + ctrl.defaultData.data, + "mixDatabaseColumnName", + attributeName + ) + ); + mixDatabaseColumn; + ctrl.mixDataContent.data.push(attr); } - }); - }; - - ctrl.view = function (item) { - var obj = { - columns: ctrl.database.columns, - item: item, - }; - $rootScope.preview("mix-db-data", obj, null, "modal-lg"); + return attr; + } }; }, ], @@ -14227,986 +14690,876 @@ modules.component("mixDatabaseNestedDataValues", { ], }); -modules.component("mixDbDataForm", { +modules.component("mixDatabaseColumn", { templateUrl: - "/mix-app/views/app-portal/components/mix-db-data-form/view.html", + "/mix-app/views/app-portal/components/mix-db-table-column/view.html", bindings: { - database: "=?", - mixDbTableId: "=?", - mixDbTableName: "=?", - mixDatabaseTitle: "=?", - mixDatabaseType: "=?", - parentId: "=?", - parentType: "=?", // MixContentType - parentName: "=?", - postId: "=?", - pageId: "=?", - moduleId: "=?", - columns: "=?", - references: "=?", - mixDataContentId: "=?", - mixDataContent: "=?", - intParentId: "=?", - guidParentId: "=?", - defaultId: "=", - backUrl: "=?", - level: "=?", - hideAction: "=?", - hiddenColumns: "=?", - onSave: "&?", - onSaveSuccess: "&?", + column: "=", }, controller: [ "$rootScope", "$scope", - "$routeParams", - "$location", - "RestMixAssociationPortalService", - "RestMixDbTablePortalService", - "MixDbDataService", - "AuthService", - function ( - $rootScope, - $scope, - $routeParams, - $location, - associationService, - databaseService, - service, - authService - ) { + "RestMixDbColumnPortalService", + function ($rootScope, $scope, columnService) { var ctrl = this; - var endpoints = JSON.parse(localStorage.getItem("ls.endpoints") || "{}"); - BaseHub.call(this, ctrl, endpoints.Messenger); - - ctrl.isBusy = true; - ctrl.attributes = []; - ctrl.isInRole = $rootScope.isInRole; - ctrl.defaultData = null; - ctrl.selectedProp = null; + ctrl.value = {}; + ctrl.column = { + dataType: "Text", + mixDbTableName: "sysAdditionalColumn", + mixDbTableId: 6, + }; + ctrl.selectedCol = null; ctrl.mixConfigurations = $rootScope.globalSettings; - - ctrl.init = async function () { - ctrl.level = ctrl.level || 0; - ctrl.canSave = ctrl.onSave != undefined; - if (!ctrl.database) { - let getDatabase = await databaseService.getByName( - ctrl.mixDbTableName + ctrl.$onInit = async function () {}; + ctrl.addAttr = async function () { + if (ctrl.column.name) { + var current = $rootScope.findObjectByKey( + ctrl.additionalData.columns, + "name", + ctrl.column.name ); - ctrl.database = getDatabase.data; - } - ctrl.fieldNames = { - id: ctrl.database.namingConvention == "TitleCase" ? "Id" : "id", - parentId: - ctrl.database.namingConvention == "TitleCase" - ? "ParentId" - : "parent_id", - parentDatabaseName: - ctrl.database.namingConvention == "TitleCase" - ? "ParentDatabaseName" - : "parent_database_name", - childId: - ctrl.database.namingConvention == "TitleCase" - ? "ChildId" - : "child_id", - childDatabaseName: - ctrl.database.namingConvention == "TitleCase" - ? "ChildDatabaseName" - : "child_database_name", - createdDateTime: - ctrl.database.namingConvention == "TitleCase" - ? "CreatedDateTime" - : "created_date_time", - lastModified: - ctrl.database.namingConvention == "TitleCase" - ? "LastModified" - : "last_modified", - tenantId: - ctrl.database.namingConvention == "TitleCase" - ? "TenantId" - : "mix_tenant_id", - createdBy: - ctrl.database.namingConvention == "TitleCase" - ? "CreatedBy" - : "created_by", - modifiedBy: - ctrl.database.namingConvention == "TitleCase" - ? "ModifiedBy" - : "modified_by", - priority: - ctrl.database.namingConvention == "TitleCase" - ? "Priority" - : "priority", - status: - ctrl.database.namingConvention == "TitleCase" ? "Status" : "status", - isDeleted: - ctrl.database.namingConvention == "TitleCase" - ? "IsDeleted" - : "is_deleted", - }; - await service.initDbName(ctrl.mixDbTableName); - await ctrl.loadData(); - ctrl.connectHub(); - ctrl.isBusy = false; - $scope.$apply(); - }; - ctrl.connectHub = () => { - ctrl.startConnection( - "mixDbHub", - authService.authentication.accessToken, - (err) => { - if ( - authService.authentication.refreshToken && - err.message.indexOf("401") >= 0 - ) { - authService.refreshToken().then(async () => { - $scope.startConnection( - "mixDbHub", - authService.authentication.accessToken - ); - }); + if (current) { + $rootScope.showErrors(["Field " + ctrl.column.name + " existed!"]); + } else { + ctrl.column.priority = ctrl.additionalData.columns.length + 1; + $rootScope.isBusy = true; + var saveField = await columnService.create(ctrl.column); + $rootScope.isBusy = false; + if (saveField.success) { + ctrl.additionalData.columns.push(saveField.data); + + //reset column option + ctrl.column.title = ""; + ctrl.column.name = ""; + ctrl.column.dataType = "Text"; + $scope.$apply(); } } - ); + } else { + $rootScope.showErrors(["Please add column Name"]); + } }; - ctrl.onConnected = () => { - ctrl.joinRooms(); + + ctrl.generateName = function (col) { + col.systemName = $rootScope.generateKeyword(col.displayName, "_", true); }; - ctrl.joinRooms = function () { - ctrl.connection.invoke("JoinRooms", [ctrl.mixDbTableName]); + ctrl.showReferences = function (col) { + ctrl.colRef = col; + $("#modal-navs").modal("show"); }; - ctrl.hubCreateData = function () { - let msg = { - connectionId: ctrl.hubRequest.from.connectionId, - mixDbName: ctrl.mixDbTableName, - requestedBy: "", - body: ctrl.mixDataContent, - }; - if (!ctrl.mixDataContent.id) { - ctrl.connection.invoke("CreateData", JSON.stringify(msg)); - } else { - ctrl.connection.invoke("UpdateData", JSON.stringify(msg)); + ctrl.referenceCallback = function (selected) { + if (selected && selected.length) { + ctrl.colRef.reference = selected; + ctrl.colRef.referenceId = selected[0].id; } - $rootScope.showMessage("Request Sent", "success"); + $("#modal-navs").modal("hide"); }; - ctrl.receiveMessage = function (msg) { - switch (msg.action) { - case "MyConnection": - ctrl.hubRequest.from = msg.data; - break; - case "NewMessage": - if (msg.type == "Success") { - $rootScope.showMessage(msg.title, "success"); - ctrl.back(); - } - if (msg.type == "Error") { - $rootScope.showErrors([msg.title]); - } - break; + ctrl.updateOrders = function (index) { + if (index > ctrl.dragStartIndex) { + ctrl.columns.splice(ctrl.dragStartIndex, 1); + } else { + ctrl.columns.splice(ctrl.dragStartIndex + 1, 1); } + angular.forEach(ctrl.columns, function (e, i) { + e.priority = i; + }); }; - ctrl.back = function () { - if (ctrl.backUrl) { - $location.url(ctrl.backUrl); + + ctrl.dragStart = function (index) { + ctrl.dragStartIndex = index; + }; + + ctrl.removeAttribute = function (val, index) { + $rootScope.showConfirm( + ctrl, + "removeAttributeConfirmed", + [val, index], + null, + "Remove Field", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + ctrl.removeAttributeConfirmed = async function (val, index) { + if (val.id) { + $rootScope.isBusy = true; + var result = await columnService.delete([val.id]); + if (result.success) { + ctrl.additionalData.columns.splice(index, 1); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(result.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } } else { - window.history.back(); + ctrl.additionalData.columns.splice(index, 1); } }; - ctrl.translate = (keyword) => { - return $rootScope.translate(keyword); + }, + ], +}); + +modules.component("mixFileExtract", { + templateUrl: + "/mix-app/views/app-portal/components/mix-file-extract/view.html", + bindings: { + folder: "=?", + accept: "=?", + onFail: "&?", + onSuccess: "&?", + }, + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "FileServices", + function ($rootScope, $scope, ngAppSettings, fileService) { + var ctrl = this; + ctrl.mediaFile = {}; + ctrl.isAdmin = $rootScope.isAdmin; + ctrl.mediaNavs = []; + ctrl.$onInit = function () { + ctrl.id = Math.floor(Math.random() * 100); }; - ctrl.loadData = async function () { - /* - If input is data id => load ctrl.mixDataContent from service and handle it independently - */ - ctrl.isBusy = true; - if (!ctrl.mixDataContent && ctrl.mixDataContentId) { - await ctrl.loadExistingData(); - } - if ( - !ctrl.mixDataContent && - (ctrl.mixDbTableName || ctrl.mixDbTableId) && - !ctrl.defaultData - ) { - ctrl.mixDataContent = {}; - if (ctrl.parentId) { - if (ctrl.database.rela) - ctrl.mixDataContent[ctrl.fieldNames.parentId] = ctrl.parentId; - } - // await ctrl.loadDefaultModel(); - ctrl.isBusy = false; - } - if ($routeParams.parentId) { - var relationship = $routeParams.relationship || "OneToMany"; - if (relationship == "OneToMany") { - if (ctrl.database.namingConvention == "SnakeCase") { - ctrl.mixDataContent[`${$routeParams.parentName}_id`] = - $routeParams.parentId; - } else { - ctrl.mixDataContent[`${$routeParams.parentName}Id`] = - $routeParams.parentId; - } + ctrl.selectFile = function (files) { + if (files !== undefined && files !== null && files.length > 0) { + const file = files[0]; + ctrl.file = file; + ctrl.mediaFile.folder = ctrl.folder ? ctrl.folder : "Media"; + ctrl.mediaFile.title = ctrl.title ? ctrl.title : ""; + ctrl.mediaFile.description = ctrl.description ? ctrl.description : ""; + ctrl.mediaFile.file = file; + if (ctrl.auto == "true") { + ctrl.uploadFile(file); } else { - ctrl.mixDataContent[ctrl.fieldNames.parentId] = - $routeParams.parentId; - ctrl.mixDataContent[ctrl.fieldNames.parentDatabaseName] = - $routeParams.parentName; - ctrl.mixDataContent[ctrl.fieldNames.childDatabaseName] = - ctrl.mixDbTableName; + ctrl.getBase64(file); } } - $scope.$apply(); - // TODO: refactor db relationship - // if ($routeParams.parentId && $routeParams.parentName) { - // var getAssociation = await associationService.getAssociation( - // $routeParams.parentName, - // ctrl.mixDbTableName, - // $routeParams.parentId, - // ctrl.mixDataContent.id - // ); - // if (getAssociation.success) { - // ctrl.association = getAssociation.data; - // } else { - // ctrl.association = { - // parentId: $routeParams.parentId, - // parentDatabaseName: $routeParams.parentName, - // childDatabaseName: ctrl.mixDbTableName, - // }; - // } - // var parentIdNameFieldName = `${$routeParams.parentName - // .charAt(0) - // .toLowerCase()}${ - // $routeParams.parentName.slice(1) || $routeParams.parentName - // }Id`; - // if (!ctrl.mixDataContent[parentIdNameFieldName]) { - // ctrl.mixDataContent[parentIdNameFieldName] = $routeParams.parentId; - // } - // } }; - ctrl.loadExistingData = async function () { - service.initDbName(ctrl.mixDbTableName); - var getData = await service.getSingle([ctrl.mixDataContentId], { - loadNestedData: true, - }); - ctrl.mixDataContent = getData.data; - if (ctrl.mixDataContent) { - ctrl.mixDatabaseTitle = - ctrl.mixDatabaseTitle || - $routeParams.mixDatabaseTitle || - ctrl.mixDbTableName; - ctrl.backUrl = - ctrl.backUrl ?? - `/admin/mix-db-data/list?mixDbTableId=${ctrl.mixDataContent.mixDbTableId}&mixDbTableName=${ctrl.mixDbTableName}&mixDatabaseTitle=${ctrl.mixDatabaseTitle}`; - // await ctrl.loadDefaultModel(); - ctrl.isBusy = false; + + ctrl.getBase64 = function (file) { + if (file !== null) { + $rootScope.isBusy = true; + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = function () { + if (ctrl.mediaFile) { + ctrl.mediaFile.fileName = file.name.substring( + 0, + file.name.lastIndexOf(".") + ); + ctrl.mediaFile.extension = file.name.substring( + file.name.lastIndexOf(".") + ); + ctrl.mediaFile.fileBase64 = reader.result; + } + $rootScope.isBusy = false; + $scope.$apply(); + }; + reader.onerror = function (error) { + $rootScope.isBusy = false; + $rootScope.showErrors([error]); + }; } else { - if (getData) { - $rootScope.showErrors(getData.errors); - } - ctrl.isBusy = false; + return null; } - $scope.$apply(); - }; - ctrl.reload = async function () { - ctrl.mixDataContent = angular.copy(ctrl.defaultData); }; - ctrl.loadSelected = function () { - if (ctrl.selectedList.data.length) { - ctrl.mixDataContent = ctrl.selectedList.data[0]; - ctrl.mixDataContent.mixDbTableId = ctrl.mixDbTableId; - ctrl.mixDataContent.mixDbTableName = ctrl.mixDbTableName; - if (ctrl.parentId) { - ctrl.mixDataContent[ctrl.fieldNames.parentId] = ctrl.parentId; - } - if (ctrl.guidParentId) { - ctrl.mixDataContent[ctrl.fieldNames.parentId] = ctrl.guidParentId; + + ctrl.uploadFile = async function () { + if (ctrl.file) { + $rootScope.isBusy = true; + var response = await fileService.extractFile(ctrl.file, ctrl.folder); + if (response) { + if (ctrl.onSuccess) { + ctrl.onSuccess(); + } + $rootScope.showMessage("success", "success"); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(["Cannot upload file"]); + $rootScope.isBusy = false; + $scope.$apply(); } - ctrl.mixDataContent.parentType = ctrl.parentType; + } else { + $rootScope.showErrors(["Please choose file"]); } }; - ctrl.submit = async function () { - if (ctrl.validate()) { - if (ctrl.onSave) { - ctrl.onSave({ data: ctrl.mixDataContent }); - } else { - ctrl.isBusy = true; - service.initDbName(ctrl.mixDbTableName); - var saveResult = await service.save(ctrl.mixDataContent); - if (saveResult.success) { - ctrl.mixDataContent = saveResult.data; - if (ctrl.association) { - let result = await ctrl.saveAssociation(ctrl.mixDataContent); - if (result.success) { - ctrl.isBusy = false; - $rootScope.showMessage("success"); - $scope.$apply(); - } else { - ctrl.isBusy = false; - $rootScope.showErrors(result.errors); - $scope.$apply(); - } - } else { - if (ctrl.onSaveSuccess) { - ctrl.onSaveSuccess({ data: ctrl.mixDataContent }); - } - ctrl.isBusy = false; - $rootScope.showMessage("success"); - $scope.$apply(); - } - } else { - ctrl.isBusy = false; - if (saveResult) { - $rootScope.showErrors(saveResult.errors); - } - $scope.$apply(); - } + }, + ], +}); + +modules.component("mixFileUpload", { + templateUrl: "/mix-app/views/app-portal/components/mix-file-upload/view.html", + bindings: { + folder: "=?", + accept: "=?", + onFail: "&?", + onSuccess: "&?", + }, + controller: [ + "$rootScope", + "$scope", + "ngAppSettings", + "FileServices", + function ($rootScope, $scope, ngAppSettings, fileService) { + var ctrl = this; + ctrl.mediaFile = {}; + ctrl.isAdmin = $rootScope.isAdmin; + ctrl.mediaNavs = []; + ctrl.$onInit = function () { + ctrl.id = Math.floor(Math.random() * 100); + }; + ctrl.selectFile = function (files) { + if (files !== undefined && files !== null && files.length > 0) { + const file = files[0]; + ctrl.file = file; + ctrl.mediaFile.folder = ctrl.folder ? ctrl.folder : "Media"; + ctrl.mediaFile.title = ctrl.title ? ctrl.title : ""; + ctrl.mediaFile.description = ctrl.description ? ctrl.description : ""; + ctrl.mediaFile.file = file; + if (ctrl.auto == "true") { + ctrl.uploadFile(file); + } else { + ctrl.getBase64(file); } } }; - ctrl.saveAssociation = async function (data) { - ctrl.association.childId = data.id; - return await associationService.save(ctrl.association); + + ctrl.getBase64 = function (file) { + if (file !== null) { + $rootScope.isBusy = true; + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = function () { + if (ctrl.mediaFile) { + ctrl.mediaFile.fileName = file.name.substring( + 0, + file.name.lastIndexOf(".") + ); + ctrl.mediaFile.extension = file.name.substring( + file.name.lastIndexOf(".") + ); + ctrl.mediaFile.fileBase64 = reader.result; + } + $rootScope.isBusy = false; + $scope.$apply(); + }; + reader.onerror = function (error) { + $rootScope.isBusy = false; + $rootScope.showErrors([error]); + }; + } else { + return null; + } }; - ctrl.validate = function () { - var isValid = true; - ctrl.errors = []; - angular.forEach(ctrl.columns, function (column) { - if (column.regex) { - var regex = RegExp(column.regex, "g"); - isValid = regex.test(ctrl.mixDataContent.data[column.name]); - if (!isValid) { - ctrl.errors.push(`${column.name} is not match Regex`); + + ctrl.uploadFile = async function () { + if (ctrl.file) { + $rootScope.isBusy = true; + var response = await fileService.uploadFile(ctrl.file, ctrl.folder); + if (response) { + if (ctrl.onSuccess) { + ctrl.onSuccess(); } + $rootScope.showMessage("success", "success"); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(["Cannot upload file"]); + $rootScope.isBusy = false; + $scope.$apply(); } - if (!isValid) { - $rootScope.showErrors(ctrl.errors); - } - if (isValid && column.isEncrypt) { - ctrl.mixDataContent.data[column.name] = $rootScope.encrypt( - ctrl.mixDataContent.data[column.name] - ); - } - }); - return isValid; - }; - ctrl.showContentFilter = function ($event) { - $rootScope.showContentFilter(ctrl.loadSelectedLink); - }; - ctrl.loadSelectedLink = function (data, type) { - if (data) { - ctrl.mixDataContent.data.target_id = data.id; - ctrl.mixDataContent.data.title = data.title; - ctrl.mixDataContent.data.type = type; - ctrl.mixDataContent.data.uri = data.detailUrl; + } else { + $rootScope.showErrors(["Please choose file"]); } }; - ctrl.filterData = function (attributeName) { - if (ctrl.mixDataContent) { - var attr = $rootScope.findObjectByKey( - ctrl.mixDataContent.data, - "mixDatabaseColumnName", - attributeName + }, + ], +}); + +"use strict"; +app.controller("MixNavigationController", [ + "$scope", + "$rootScope", + "ngAppSettings", + "$routeParams", + "MediaService", + "ApiService", + "CommonService", + function ( + $scope, + $rootScope, + ngAppSettings, + $routeParams, + service, + apiService, + commonService + ) { + BaseCtrl.call( + this, + $scope, + $rootScope, + $routeParams, + ngAppSettings, + service + ); + + $scope.viewmodel = { + title: "", + description: "", + status: "Published", + mediaFile: { + file: null, + fullPath: "", + folderName: "Media", + fileFolder: "", + fileName: "", + extension: "", + content: "", + fileBase64: "", + }, + }; + $scope.relatedMedias = []; + $scope.uploadMedia = async function () { + $rootScope.isBusy = true; + var resp = await service.uploadMedia($scope.mediaFile); + if (resp && resp.success) { + $scope.activedMedia = resp.data.url; + $scope.getList(); + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.selectFile = function (file, errFiles) { + if (file !== undefined && file !== null) { + $scope.mediaFile.folder = "Media"; + $scope.mediaFile.file = file; + $scope.getBase64(file); + } + }; + $scope.getBase64 = function (file) { + if (file !== null && $scope.postedFile) { + $rootScope.isBusy = true; + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = function () { + var index = reader.result.indexOf(",") + 1; + var base64 = reader.result.substring(index); + $scope.activedMedia.mediaFile.fileName = $rootScope.generateKeyword( + file.name.substring(0, file.name.lastIndexOf(".")), + "-" ); - if (!attr) { - attr = angular.copy( - $rootScope.findObjectByKey( - ctrl.defaultData.data, - "mixDatabaseColumnName", - attributeName - ) - ); - mixDatabaseColumn; - ctrl.mixDataContent.data.push(attr); - } - return attr; + $scope.activedMedia.mediaFile.extension = file.name.substring( + file.name.lastIndexOf(".") + ); + $scope.activedMedia.mediaFile.fileBase64 = reader.result; + $rootScope.isBusy = false; + $scope.$apply(); + }; + reader.onerror = function (error) { + $rootScope.showErrors([error]); + $rootScope.isBusy = false; + }; + } else { + return null; + } + }; + $scope.togglePreview = function (item) { + item.isPreview = item.isPreview === undefined ? true : !item.isPreview; + }; + $scope.clone = async function (id) { + $rootScope.isBusy = true; + var resp = await service.cloneMedia(id); + if (resp && resp.success) { + $scope.activedMedia = resp.data; + $rootScope.showMessage("Update successfully!", "success"); + $rootScope.isBusy = false; + $scope.$apply(); + //$location.path('/admin/media/details/' + resp.data.id); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + $scope.saveSuccessCallback = function () { + $scope.getList(); + }; + $scope.removeCallback = function () { + $scope.getList(); + }; + }, +]); + +modules.component("mixSelectIcons", { + templateUrl: + "/mix-app/views/app-portal/components/mix-select-icons/mix-select-icons.html", + controller: [ + "$rootScope", + "$scope", + "$location", + "$element", + function ($rootScope, $scope, $location, $element) { + var ctrl = this; + ctrl.limitTo = 20; + ctrl.container = $element[0].querySelector(".list-icon"); + ctrl.translate = function (keyword) { + return $rootScope.translate(keyword); + }; + ctrl.showMore = () => { + if ( + ctrl.container.scrollTop >= ctrl.container.scrollHeight - 200 && + ctrl.limitTo < ctrl.options.length + ) { + ctrl.limitTo *= 2; } }; + ctrl.select = function (ico) { + ctrl.data = ico.class; + }; }, ], + bindings: { + data: "=", + prefix: "=", + options: "=", + }, }); -modules.component("mixFileExtract", { +modules.component("mixTemplateEditor", { templateUrl: - "/mix-app/views/app-portal/components/mix-file-extract/view.html", + "/mix-app/views/app-portal/components/mix-template-editor/view.html", bindings: { - folder: "=?", - accept: "=?", - onFail: "&?", - onSuccess: "&?", + template: "=", + folderType: "=", + isReadonly: "=?", + lineCount: "=?", + hideJs: "=?", + hideCss: "=?", }, controller: [ - "$rootScope", "$scope", + "$rootScope", + "$routeParams", "ngAppSettings", - "FileServices", - function ($rootScope, $scope, ngAppSettings, fileService) { + "AppSettingsService", + "TemplateService", + function ( + $scope, + $rootScope, + $routeParams, + ngAppSettings, + appSettingsService, + service + ) { + BaseCtrl.call( + this, + $scope, + $rootScope, + $routeParams, + ngAppSettings, + service + ); var ctrl = this; - ctrl.mediaFile = {}; - ctrl.isAdmin = $rootScope.isAdmin; - ctrl.mediaNavs = []; - ctrl.$onInit = function () { - ctrl.id = Math.floor(Math.random() * 100); + ctrl.isNull = false; + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.selectPane = function (pane) { + ctrl.activedPane = pane; }; - ctrl.selectFile = function (files) { - if (files !== undefined && files !== null && files.length > 0) { - const file = files[0]; - ctrl.file = file; - ctrl.mediaFile.folder = ctrl.folder ? ctrl.folder : "Media"; - ctrl.mediaFile.title = ctrl.title ? ctrl.title : ""; - ctrl.mediaFile.description = ctrl.description ? ctrl.description : ""; - ctrl.mediaFile.file = file; - if (ctrl.auto == "true") { - ctrl.uploadFile(file); - } else { - ctrl.getBase64(file); - } - } + ctrl.selectTemplate = function (template) { + ctrl.template = template; + $scope.$broadcast("updateContentCodeEditors", []); }; - - ctrl.getBase64 = function (file) { - if (file !== null) { - $rootScope.isBusy = true; - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function () { - if (ctrl.mediaFile) { - ctrl.mediaFile.fileName = file.name.substring( - 0, - file.name.lastIndexOf(".") - ); - ctrl.mediaFile.extension = file.name.substring( - file.name.lastIndexOf(".") - ); - ctrl.mediaFile.fileBase64 = reader.result; - } - $rootScope.isBusy = false; - $scope.$apply(); - }; - reader.onerror = function (error) { - $rootScope.isBusy = false; - $rootScope.showErrors([error]); - }; - } else { - return null; - } + ctrl.new = function () { + ctrl.template.id = 0; }; + ctrl.init = async function () { + if (ctrl.folderType) { + var themeId = $rootScope.mixConfigurations.data.ThemeId; + ctrl.request.key = ctrl.folderType; + var resp = await service.getList(ctrl.request, [themeId]); - ctrl.uploadFile = async function () { - if (ctrl.file) { - $rootScope.isBusy = true; - var response = await fileService.extractFile(ctrl.file, ctrl.folder); - if (response) { - if (ctrl.onSuccess) { - ctrl.onSuccess(); + if (resp && resp.success) { + ctrl.templates = resp.data.items; + if (!ctrl.template) { + ctrl.template = ctrl.templates[0]; } - $rootScope.showMessage("success", "success"); $rootScope.isBusy = false; $scope.$apply(); } else { - $rootScope.showErrors(["Cannot upload file"]); - $rootScope.isBusy = false; - $scope.$apply(); + if (resp) { + $rootScope.showErrors(resp.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } } - } else { - $rootScope.showErrors(["Please choose file"]); } }; + ctrl.updateTemplateContent = function (content) { + ctrl.template.content = content; + }; + ctrl.updateStyleContent = function (content) { + ctrl.template.scripts = content; + }; + ctrl.updateScriptContent = function (content) { + ctrl.template.styles = content; + }; }, ], }); -modules.component("mixDatabaseColumn", { +modules.component("modalBookmark", { templateUrl: - "/mix-app/views/app-portal/components/mix-db-table-column/view.html", - bindings: { - column: "=", - }, + "/mix-app/views/app-portal/components/modal-bookmark/modal-bookmark.html", controller: [ "$rootScope", "$scope", - "RestMixDbColumnPortalService", - function ($rootScope, $scope, columnService) { + "localStorageService", + "$routeParams", + "$location", + function ( + $rootScope, + $scope, + localStorageService, + $routeParams, + $location + ) { var ctrl = this; - ctrl.value = {}; - ctrl.column = { - dataType: "Text", - mixDbTableName: "sysAdditionalColumn", - mixDbTableId: 6, - }; - ctrl.selectedCol = null; - ctrl.mixConfigurations = $rootScope.globalSettings; - ctrl.$onInit = async function () {}; - ctrl.addAttr = async function () { - if (ctrl.column.name) { - var current = $rootScope.findObjectByKey( - ctrl.additionalData.columns, - "name", - ctrl.column.name - ); - if (current) { - $rootScope.showErrors(["Field " + ctrl.column.name + " existed!"]); - } else { - ctrl.column.priority = ctrl.additionalData.columns.length + 1; - $rootScope.isBusy = true; - var saveField = await columnService.create(ctrl.column); - $rootScope.isBusy = false; - if (saveField.success) { - ctrl.additionalData.columns.push(saveField.data); - - //reset column option - ctrl.column.title = ""; - ctrl.column.name = ""; - ctrl.column.dataType = "Text"; - $scope.$apply(); - } - } - } else { - $rootScope.showErrors(["Please add column Name"]); - } - }; - - ctrl.generateName = function (col) { - col.systemName = $rootScope.generateKeyword(col.displayName, "_", true); - }; - ctrl.showReferences = function (col) { - ctrl.colRef = col; - $("#modal-navs").modal("show"); - }; - ctrl.referenceCallback = function (selected) { - if (selected && selected.length) { - ctrl.colRef.reference = selected; - ctrl.colRef.referenceId = selected[0].id; - } - $("#modal-navs").modal("hide"); + ctrl.searchText = ""; + ctrl.defaultModel = { + url: "", + title: "", }; - ctrl.updateOrders = function (index) { - if (index > ctrl.dragStartIndex) { - ctrl.columns.splice(ctrl.dragStartIndex, 1); - } else { - ctrl.columns.splice(ctrl.dragStartIndex + 1, 1); - } - angular.forEach(ctrl.columns, function (e, i) { - e.priority = i; - }); + ctrl.bookmarks = []; + ctrl.model = null; + ctrl.$onInit = function () { + ctrl.model = angular.copy(ctrl.defaultModel); + ctrl.getCurrentUrl(); + ctrl.bookmarks = localStorageService.get("bookmarks") || []; }; - - ctrl.dragStart = function (index) { - ctrl.dragStartIndex = index; + ctrl.goToPath = function (url) { + $rootScope.goToPath(url); + $("#dlg-bookmark").modal("hide"); }; - - ctrl.removeAttribute = function (val, index) { - $rootScope.showConfirm( - ctrl, - "removeAttributeConfirmed", - [val, index], - null, - "Remove Field", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); + ctrl.getCurrentUrl = function (url) { + url = url || $location.url(); + ctrl.model.url = url; + ctrl.model.title = url; }; - ctrl.removeAttributeConfirmed = async function (val, index) { - if (val.id) { - $rootScope.isBusy = true; - var result = await columnService.delete([val.id]); - if (result.success) { - ctrl.additionalData.columns.splice(index, 1); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(result.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } + ctrl.removeBookmark = function (url) { + $rootScope.removeObjectByKey(ctrl.bookmarks, "url", url); + localStorageService.set("bookmarks", ctrl.bookmarks); + }; + ctrl.addBookmark = function () { + var current = $rootScope.findObjectByKey( + ctrl.bookmarks, + "url", + ctrl.model.url + ); + if (current) { + current.title = ctrl.model.title; } else { - ctrl.additionalData.columns.splice(index, 1); + ctrl.bookmarks.push(ctrl.model); } + localStorageService.set("bookmarks", ctrl.bookmarks); + ctrl.model = angular.copy(ctrl.defaultModel); }; }, ], }); -modules.component("mixFileUpload", { - templateUrl: "/mix-app/views/app-portal/components/mix-file-upload/view.html", +modules.component("mixValueEditor", { + templateUrl: + "/mix-app/views/app-portal/components/mix-value-editor/view.html", bindings: { - folder: "=?", - accept: "=?", - onFail: "&?", - onSuccess: "&?", + title: "=?", + isSelect: "=?", + stringValue: "=", + type: "=", }, controller: [ "$rootScope", "$scope", "ngAppSettings", - "FileServices", - function ($rootScope, $scope, ngAppSettings, fileService) { + "$location", + "RestMixDbDataPortalService", + function ($rootScope, $scope, ngAppSettings, $location, dataService) { var ctrl = this; - ctrl.mediaFile = {}; - ctrl.isAdmin = $rootScope.isAdmin; - ctrl.mediaNavs = []; - ctrl.$onInit = function () { - ctrl.id = Math.floor(Math.random() * 100); - }; - ctrl.selectFile = function (files) { - if (files !== undefined && files !== null && files.length > 0) { - const file = files[0]; - ctrl.file = file; - ctrl.mediaFile.folder = ctrl.folder ? ctrl.folder : "Media"; - ctrl.mediaFile.title = ctrl.title ? ctrl.title : ""; - ctrl.mediaFile.description = ctrl.description ? ctrl.description : ""; - ctrl.mediaFile.file = file; - if (ctrl.auto == "true") { - ctrl.uploadFile(file); - } else { - ctrl.getBase64(file); + ctrl.icons = ngAppSettings.icons; + ctrl.refData = []; + ctrl.refRequest = angular.copy(ngAppSettings.request); + ctrl.refRequest.pageSize = 100; + ctrl.dataTypes = $rootScope.globalSettings.dataTypes; + ctrl.previousId = null; + ctrl.initData = async function () { + setTimeout(() => { + switch (ctrl.type) { + case "datetime": + case "date": + case "time": + if (ctrl.stringValue) { + ctrl.dateObj = new Date(ctrl.stringValue); + $scope.$apply(); + } + break; + case "boolean": + if (ctrl.stringValue) { + ctrl.booleanValue = ctrl.stringValue == "true"; + } + break; + + case "reference": // reference + if (ctrl.referenceId) { + ctrl.refRequest.mixDbTableId = ctrl.referenceId; + ctrl.refRequest.parentType = ctrl.parentType; + ctrl.refRequest.parentId = ctrl.parentId; + + dataService.getList(ctrl.refRequest).then((resp) => { + if (resp) { + ctrl.refData = resp; + $rootScope.isBusy = false; + $scope.$apply(); + } else { + if (resp) { + $rootScope.showErrors(resp.errors); + } + $rootScope.isBusy = false; + $scope.$apply(); + } + }); + } + break; + default: + if (ctrl.isEncrypt && ctrl.encryptValue) { + var encryptedData = { + key: ctrl.encryptKey, + data: ctrl.encryptValue, + }; + ctrl.stringValue = $rootScope.decrypt(encryptedData); + } + break; } - } + }, 200); }; - - ctrl.getBase64 = function (file) { - if (file !== null) { - $rootScope.isBusy = true; - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function () { - if (ctrl.mediaFile) { - ctrl.mediaFile.fileName = file.name.substring( - 0, - file.name.lastIndexOf(".") - ); - ctrl.mediaFile.extension = file.name.substring( - file.name.lastIndexOf(".") - ); - ctrl.mediaFile.fileBase64 = reader.result; + ctrl.updateStringValue = async function (dataType) { + switch (dataType) { + case "datetime": + case "date": + case "time": + if (ctrl.dateObj != null) { + ctrl.stringValue = ctrl.dateObj.toISOString(); + } else { + ctrl.stringValue = null; } - $rootScope.isBusy = false; - $scope.$apply(); - }; - reader.onerror = function (error) { - $rootScope.isBusy = false; - $rootScope.showErrors([error]); - }; - } else { - return null; + break; + case "double": + // ctrl.stringValue = ctrl.doubleValue; + break; + case "boolean": + // ctrl.stringValue = ctrl.booleanValue; + break; + + default: + ctrl.stringValue = ctrl.doubleValue; + break; } }; - - ctrl.uploadFile = async function () { - if (ctrl.file) { - $rootScope.isBusy = true; - var response = await fileService.uploadFile(ctrl.file, ctrl.folder); - if (response) { - if (ctrl.onSuccess) { - ctrl.onSuccess(); - } - $rootScope.showMessage("success", "success"); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(["Cannot upload file"]); - $rootScope.isBusy = false; - $scope.$apply(); - } + ctrl.updateRefData = function (item) { + $location.url( + "/admin/mix-db-data/details?dataContentId=" + + item.id + + "&mixDbTableId=" + + item.mixDbTableId + + "&parentType=" + + item.parentType + + "&parentId=" + + item.parentId + ); + }; + ctrl.removeRefData = async function (data) { + $rootScope.showConfirm( + ctrl, + "removeRefDataConfirmed", + [data.id], + null, + "Remove", + "Deleted data will not able to recover, are you sure you want to delete this item?" + ); + }; + ctrl.removeRefDataConfirmed = async function (dataContentId) { + $rootScope.isBusy = true; + var result = await dataService.delete(dataContentId); + if (result.success) { + $rootScope.removeObjectByKey(ctrl.refData, "id", dataContentId); + $rootScope.isBusy = false; + $scope.$apply(); } else { - $rootScope.showErrors(["Please choose file"]); + $rootScope.showErrors(result.errors); + $rootScope.isBusy = false; + $scope.$apply(); } }; }, ], }); -modules.component("mixSelectIcons", { - templateUrl: - "/mix-app/views/app-portal/components/mix-select-icons/mix-select-icons.html", - controller: [ - "$rootScope", - "$scope", - "$location", - "$element", - function ($rootScope, $scope, $location, $element) { - var ctrl = this; - ctrl.limitTo = 20; - ctrl.container = $element[0].querySelector(".list-icon"); - ctrl.translate = function (keyword) { - return $rootScope.translate(keyword); - }; - ctrl.showMore = () => { - if ( - ctrl.container.scrollTop >= ctrl.container.scrollHeight - 200 && - ctrl.limitTo < ctrl.options.length - ) { - ctrl.limitTo *= 2; - } - }; - ctrl.select = function (ico) { - ctrl.data = ico.class; - }; - }, - ], - bindings: { - data: "=", - prefix: "=", - options: "=", +app.component("modalCroppie", { + templateUrl: "/mix-app/views/app-portal/components/modal-croppie/view.html", + bidings: { + resolve: "<", + close: "&", + dismiss: "&", + }, + controller: function () { + var $ctrl = this; + $ctrl.fileUrl = "test"; + $ctrl.$onInit = function () { + $ctrl.file = $ctrl.resolve.file; + }; + + $ctrl.ok = function () { + $ctrl.close({ $value: $ctrl.fileUrl }); + }; + + $ctrl.cancel = function () { + $ctrl.dismiss({ $value: "cancel" }); + }; }, }); -modules.component("mixTemplateEditor", { +modules.component("modalHelper", { templateUrl: - "/mix-app/views/app-portal/components/mix-template-editor/view.html", + "/mix-app/views/app-portal/components/modal-helper/modal-helper.html", bindings: { - template: "=", - folderType: "=", - isReadonly: "=?", - lineCount: "=?", - hideJs: "=?", - hideCss: "=?", + url: "=?", + title: "=?", }, controller: [ - "$scope", "$rootScope", + "$scope", + "localStorageService", "$routeParams", - "ngAppSettings", - "AppSettingsService", - "TemplateService", + "$location", + "$sce", function ( - $scope, $rootScope, + $scope, + localStorageService, $routeParams, - ngAppSettings, - appSettingsService, - service + $location, + $sce ) { - BaseCtrl.call( - this, - $scope, - $rootScope, - $routeParams, - ngAppSettings, - service - ); var ctrl = this; - ctrl.isNull = false; - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.selectPane = function (pane) { - ctrl.activedPane = pane; - }; - ctrl.selectTemplate = function (template) { - ctrl.template = template; - $scope.$broadcast("updateContentCodeEditors", []); - }; - ctrl.new = function () { - ctrl.template.id = 0; - }; - ctrl.init = async function () { - if (ctrl.folderType) { - var themeId = $rootScope.mixConfigurations.data.ThemeId; - ctrl.request.key = ctrl.folderType; - var resp = await service.getList(ctrl.request, [themeId]); - - if (resp && resp.success) { - ctrl.templates = resp.data.items; - if (!ctrl.template) { - ctrl.template = ctrl.templates[0]; - } - $rootScope.isBusy = false; - $scope.$apply(); + ctrl.$onInit = function () { + $("#dev-helper-modal").on("shown.bs.modal", function () { + if ($rootScope.helperUrl) { + ctrl.trustedUrl = $sce.trustAsResourceUrl($rootScope.helperUrl); + ctrl.title = "Developer Document"; } else { - if (resp) { - $rootScope.showErrors(resp.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } + ctrl.loadHelperUrl(); + ctrl.title = "Developer Document"; } - } - }; - ctrl.updateTemplateContent = function (content) { - ctrl.template.content = content; - }; - ctrl.updateStyleContent = function (content) { - ctrl.template.scripts = content; - }; - ctrl.updateScriptContent = function (content) { - ctrl.template.styles = content; + $rootScope.helperUrl = null; + $scope.$apply(); + }); }; - }, - ], -}); - -"use strict"; -app.controller("MixNavigationController", [ - "$scope", - "$rootScope", - "ngAppSettings", - "$routeParams", - "MediaService", - "ApiService", - "CommonService", - function ( - $scope, - $rootScope, - ngAppSettings, - $routeParams, - service, - apiService, - commonService - ) { - BaseCtrl.call( - this, - $scope, - $rootScope, - $routeParams, - ngAppSettings, - service - ); + ctrl.loadHelperUrl = function () { + var portalUrl = $location.url(); + // var portalabsUrl = $location.absUrl(); + var defaultUrl = "//docs.mixcore.org"; + ctrl.trustedUrl = $sce.trustAsResourceUrl(defaultUrl); - $scope.viewmodel = { - title: "", - description: "", - status: "Published", - mediaFile: { - file: null, - fullPath: "", - folderName: "Media", - fileFolder: "", - fileName: "", - extension: "", - content: "", - fileBase64: "", - }, - }; - $scope.relatedMedias = []; - $scope.uploadMedia = async function () { - $rootScope.isBusy = true; - var resp = await service.uploadMedia($scope.mediaFile); - if (resp && resp.success) { - $scope.activedMedia = resp.data.url; - $scope.getList(); - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); + if (portalUrl.startsWith("/admin")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-administration-screens" + ); } - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.selectFile = function (file, errFiles) { - if (file !== undefined && file !== null) { - $scope.mediaFile.folder = "Media"; - $scope.mediaFile.file = file; - $scope.getBase64(file); - } - }; - $scope.getBase64 = function (file) { - if (file !== null && $scope.postedFile) { - $rootScope.isBusy = true; - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function () { - var index = reader.result.indexOf(",") + 1; - var base64 = reader.result.substring(index); - $scope.activedMedia.mediaFile.fileName = $rootScope.generateKeyword( - file.name.substring(0, file.name.lastIndexOf(".")), - "-" + if (portalUrl.startsWith("/admin/mix-db-data/list?mixDbTableId=2")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-navigation" ); - $scope.activedMedia.mediaFile.extension = file.name.substring( - file.name.lastIndexOf(".") + } + if (portalUrl.startsWith("/admin/post")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-writing-posts" + ); + } + if (portalUrl.startsWith("/admin/page")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-page" + ); + } + if (portalUrl.startsWith("/admin/module")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-module" + ); + } + if (portalUrl.startsWith("/admin/mix-db-table")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-database" + ); + } + if (portalUrl.startsWith("/admin/mix-db-data/list?mixDbTableId=7")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-category" + ); + } + if (portalUrl.startsWith("/admin/mix-db-data/list?mixDbTableId=8")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-tag" + ); + } + if (portalUrl.startsWith("/admin/media")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-media" + ); + } + if (portalUrl.startsWith("/admin/file")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-file" + ); + } + if (portalUrl.startsWith("/admin/user")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-user" + ); + } + if (portalUrl.startsWith("/admin/theme")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-theme" + ); + } + if (portalUrl.startsWith("/admin/app-settings")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-app-settings" ); - $scope.activedMedia.mediaFile.fileBase64 = reader.result; - $rootScope.isBusy = false; - $scope.$apply(); - }; - reader.onerror = function (error) { - $rootScope.showErrors([error]); - $rootScope.isBusy = false; - }; - } else { - return null; - } - }; - $scope.togglePreview = function (item) { - item.isPreview = item.isPreview === undefined ? true : !item.isPreview; - }; - $scope.clone = async function (id) { - $rootScope.isBusy = true; - var resp = await service.cloneMedia(id); - if (resp && resp.success) { - $scope.activedMedia = resp.data; - $rootScope.showMessage("Update successfully!", "success"); - $rootScope.isBusy = false; - $scope.$apply(); - //$location.path('/admin/media/details/' + resp.data.id); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); } - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - $scope.saveSuccessCallback = function () { - $scope.getList(); - }; - $scope.removeCallback = function () { - $scope.getList(); - }; - }, -]); - -modules.component("modalBookmark", { - templateUrl: - "/mix-app/views/app-portal/components/modal-bookmark/modal-bookmark.html", - controller: [ - "$rootScope", - "$scope", - "localStorageService", - "$routeParams", - "$location", - function ( - $rootScope, - $scope, - localStorageService, - $routeParams, - $location - ) { - var ctrl = this; - ctrl.searchText = ""; - ctrl.defaultModel = { - url: "", - title: "", - }; - ctrl.bookmarks = []; - ctrl.model = null; - ctrl.$onInit = function () { - ctrl.model = angular.copy(ctrl.defaultModel); - ctrl.getCurrentUrl(); - ctrl.bookmarks = localStorageService.get("bookmarks") || []; - }; - ctrl.goToPath = function (url) { - $rootScope.goToPath(url); - $("#dlg-bookmark").modal("hide"); - }; - ctrl.getCurrentUrl = function (url) { - url = url || $location.url(); - ctrl.model.url = url; - ctrl.model.title = url; - }; - ctrl.removeBookmark = function (url) { - $rootScope.removeObjectByKey(ctrl.bookmarks, "url", url); - localStorageService.set("bookmarks", ctrl.bookmarks); - }; - ctrl.addBookmark = function () { - var current = $rootScope.findObjectByKey( - ctrl.bookmarks, - "url", - ctrl.model.url - ); - if (current) { - current.title = ctrl.model.title; - } else { - ctrl.bookmarks.push(ctrl.model); + if (portalUrl.startsWith("/admin/configuration")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-configuration" + ); } - localStorageService.set("bookmarks", ctrl.bookmarks); - ctrl.model = angular.copy(ctrl.defaultModel); + if (portalUrl.startsWith("/admin/my-profile")) { + ctrl.trustedUrl = $sce.trustAsResourceUrl( + defaultUrl + "/basic-usage-users-profile" + ); + } + + // switch (portalUrl) { + // case '/admin': + // default: + // ctrl.trustedUrl = $sce.trustAsResourceUrl(defaultUrl); + // break; + // } }; }, ], @@ -15331,338 +15684,189 @@ modules.component("modalContentFilter", { $rootScope.isBusy = true; var response = await pageService.getList(ctrl.request); if (response.success) { - ctrl.data = response.data; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - ctrl.select = function (nav) { - var current = $rootScope.findObjectByKey(ctrl.data.items, "id", nav.id); - if (!nav.isActive && ctrl.callback) { - ctrl.callback({ - nav: nav, - type: ctrl.type, - }); - } - if (ctrl.isMultiple) { - current.isActive = !current.isActive; - } else { - if (!nav.isActive) { - angular.forEach(ctrl.data.items, (element) => { - element.isActive = false; - }); - } - current.isActive = !nav.isActive; - } - }; - ctrl.saveSelected = function () { - ctrl.selected = $rootScope.filterArray( - ctrl.data, - ["isActived"], - [true] - ); - setTimeout(() => { - ctrl.save().then(() => { - ctrl.loadPosts(); - }); - }, 500); - }; - ctrl.limString = function (str, max) { - if (str) { - return str.length > max ? str.substring(0, max) + " ..." : str; - } - }; - }, - ], -}); - -modules.component("mixValueEditor", { - templateUrl: - "/mix-app/views/app-portal/components/mix-value-editor/view.html", - bindings: { - title: "=?", - isSelect: "=?", - stringValue: "=", - type: "=", - }, - controller: [ - "$rootScope", - "$scope", - "ngAppSettings", - "$location", - "RestMixDbDataPortalService", - function ($rootScope, $scope, ngAppSettings, $location, dataService) { - var ctrl = this; - ctrl.icons = ngAppSettings.icons; - ctrl.refData = []; - ctrl.refRequest = angular.copy(ngAppSettings.request); - ctrl.refRequest.pageSize = 100; - ctrl.dataTypes = $rootScope.globalSettings.dataTypes; - ctrl.previousId = null; - ctrl.initData = async function () { - setTimeout(() => { - switch (ctrl.type) { - case "datetime": - case "date": - case "time": - if (ctrl.stringValue) { - ctrl.dateObj = new Date(ctrl.stringValue); - $scope.$apply(); - } - break; - case "boolean": - if (ctrl.stringValue) { - ctrl.booleanValue = ctrl.stringValue == "true"; - } - break; - - case "reference": // reference - if (ctrl.referenceId) { - ctrl.refRequest.mixDbTableId = ctrl.referenceId; - ctrl.refRequest.parentType = ctrl.parentType; - ctrl.refRequest.parentId = ctrl.parentId; - - dataService.getList(ctrl.refRequest).then((resp) => { - if (resp) { - ctrl.refData = resp; - $rootScope.isBusy = false; - $scope.$apply(); - } else { - if (resp) { - $rootScope.showErrors(resp.errors); - } - $rootScope.isBusy = false; - $scope.$apply(); - } - }); - } - break; - default: - if (ctrl.isEncrypt && ctrl.encryptValue) { - var encryptedData = { - key: ctrl.encryptKey, - data: ctrl.encryptValue, - }; - ctrl.stringValue = $rootScope.decrypt(encryptedData); - } - break; - } - }, 200); - }; - ctrl.updateStringValue = async function (dataType) { - switch (dataType) { - case "datetime": - case "date": - case "time": - if (ctrl.dateObj != null) { - ctrl.stringValue = ctrl.dateObj.toISOString(); - } else { - ctrl.stringValue = null; - } - break; - case "double": - // ctrl.stringValue = ctrl.doubleValue; - break; - case "boolean": - // ctrl.stringValue = ctrl.booleanValue; - break; - - default: - ctrl.stringValue = ctrl.doubleValue; - break; - } - }; - ctrl.updateRefData = function (item) { - $location.url( - "/admin/mix-db-data/details?dataContentId=" + - item.id + - "&mixDbTableId=" + - item.mixDbTableId + - "&parentType=" + - item.parentType + - "&parentId=" + - item.parentId - ); - }; - ctrl.removeRefData = async function (data) { - $rootScope.showConfirm( - ctrl, - "removeRefDataConfirmed", - [data.id], - null, - "Remove", - "Deleted data will not able to recover, are you sure you want to delete this item?" - ); - }; - ctrl.removeRefDataConfirmed = async function (dataContentId) { - $rootScope.isBusy = true; - var result = await dataService.delete(dataContentId); - if (result.success) { - $rootScope.removeObjectByKey(ctrl.refData, "id", dataContentId); + ctrl.data = response.data; $rootScope.isBusy = false; $scope.$apply(); } else { - $rootScope.showErrors(result.errors); + $rootScope.showErrors(response.errors); $rootScope.isBusy = false; $scope.$apply(); } }; + ctrl.select = function (nav) { + var current = $rootScope.findObjectByKey(ctrl.data.items, "id", nav.id); + if (!nav.isActive && ctrl.callback) { + ctrl.callback({ + nav: nav, + type: ctrl.type, + }); + } + if (ctrl.isMultiple) { + current.isActive = !current.isActive; + } else { + if (!nav.isActive) { + angular.forEach(ctrl.data.items, (element) => { + element.isActive = false; + }); + } + current.isActive = !nav.isActive; + } + }; + ctrl.saveSelected = function () { + ctrl.selected = $rootScope.filterArray( + ctrl.data, + ["isActived"], + [true] + ); + setTimeout(() => { + ctrl.save().then(() => { + ctrl.loadPosts(); + }); + }, 500); + }; + ctrl.limString = function (str, max) { + if (str) { + return str.length > max ? str.substring(0, max) + " ..." : str; + } + }; }, ], }); -app.component("modalCroppie", { - templateUrl: "/mix-app/views/app-portal/components/modal-croppie/view.html", - bidings: { - resolve: "<", - close: "&", - dismiss: "&", - }, - controller: function () { - var $ctrl = this; - $ctrl.fileUrl = "test"; - $ctrl.$onInit = function () { - $ctrl.file = $ctrl.resolve.file; - }; - - $ctrl.ok = function () { - $ctrl.close({ $value: $ctrl.fileUrl }); - }; - - $ctrl.cancel = function () { - $ctrl.dismiss({ $value: "cancel" }); - }; - }, -}); - -modules.component("modalHelper", { - templateUrl: - "/mix-app/views/app-portal/components/modal-helper/modal-helper.html", +modules.component("modalNavDatas", { + templateUrl: "/mix-app/views/app-portal/components/modal-nav-datas/view.html", bindings: { - url: "=?", - title: "=?", + fieldNames: "=", + mixDbTableId: "=?", + relationship: "=?", + mixDbTableName: "=?", + parentDatabaseName: "=?", + guidParentId: "=?", + parentId: "=?", + parentType: "=?", + type: "=?", + columnDisplay: "=?", + selectedIds: "=?", + selectedList: "=?", + selectCallback: "&?", + save: "&", }, controller: [ "$rootScope", "$scope", - "localStorageService", - "$routeParams", "$location", - "$sce", + "$routeParams", + "ngAppSettings", + "RestMixAssociationPortalService", + "RestMixDbTablePortalService", + "MixDbDataService", function ( $rootScope, $scope, - localStorageService, - $routeParams, $location, - $sce + $routeParams, + ngAppSettings, + associationService, + databaseService, + dataService ) { var ctrl = this; - ctrl.$onInit = function () { - $("#dev-helper-modal").on("shown.bs.modal", function () { - if ($rootScope.helperUrl) { - ctrl.trustedUrl = $sce.trustAsResourceUrl($rootScope.helperUrl); - ctrl.title = "Developer Document"; - } else { - ctrl.loadHelperUrl(); - ctrl.title = "Developer Document"; - } - $rootScope.helperUrl = null; - $scope.$apply(); - }); - }; - ctrl.loadHelperUrl = function () { - var portalUrl = $location.url(); - // var portalabsUrl = $location.absUrl(); - var defaultUrl = "//docs.mixcore.org"; - ctrl.trustedUrl = $sce.trustAsResourceUrl(defaultUrl); + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.navs = []; - if (portalUrl.startsWith("/admin")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-administration-screens" - ); - } - if (portalUrl.startsWith("/admin/mix-db-data/list?mixDbTableId=2")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-navigation" - ); - } - if (portalUrl.startsWith("/admin/post")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-writing-posts" - ); - } - if (portalUrl.startsWith("/admin/page")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-page" - ); - } - if (portalUrl.startsWith("/admin/module")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-module" - ); - } - if (portalUrl.startsWith("/admin/mix-db-table")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-database" - ); - } - if (portalUrl.startsWith("/admin/mix-db-data/list?mixDbTableId=7")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-category" - ); - } - if (portalUrl.startsWith("/admin/mix-db-data/list?mixDbTableId=8")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-tag" - ); - } - if (portalUrl.startsWith("/admin/media")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-media" - ); - } - if (portalUrl.startsWith("/admin/file")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-file" + ctrl.queries = {}; + ctrl.data = { items: [] }; + ctrl.$onInit = async function () { + ctrl.association = { + parentId: ctrl.parentId, + guidParentId: ctrl.guidParentId, + parentDatabaseName: ctrl.parentDatabaseName, + childDatabaseName: ctrl.mixDbTableName, + }; + dataService.initDbName(ctrl.mixDbTableName); + ctrl.request.sortBy = ctrl.fieldNames.id; + ctrl.request.name = ctrl.mixDbTableName; + ctrl.request.parentName = ctrl.parentName; + ctrl.request.relationship = ctrl.relationship; + // ctrl.request.parentId = ctrl.parentId; + if (!ctrl.database) { + var getDatabase = await databaseService.getByName( + ctrl.mixDbTableName ); + if (getDatabase.success) { + ctrl.database = getDatabase.data; + $scope.$apply(); + } } - if (portalUrl.startsWith("/admin/user")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-user" - ); + if (!ctrl.data) { + await ctrl.loadData(); } - if (portalUrl.startsWith("/admin/theme")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-theme" - ); + }; + ctrl.showDbModel = function () { + $(`#modal-nav-data-${ctrl.mixDbTableName}`).modal("show"); + }; + ctrl.select = async (item) => { + $rootScope.isBusy = true; + if (item.isSelected && (ctrl.parentId || ctrl.guidParentId)) { + ctrl.association.childId = item.id; + let result = await dataService.createRelationship(ctrl.association); + if (result.success) { + item.associationId = result.data.id; + } + $rootScope.handleResponse(result); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + var nav = ctrl.selectedIds.find((m) => m.dataId == item.id); + let result = await dataService.deleteRelationship(nav.id); + $rootScope.handleResponse(result); + $rootScope.isBusy = false; + $scope.$apply(); } - if (portalUrl.startsWith("/admin/app-settings")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-app-settings" - ); + if (ctrl.selectCallback) { + ctrl.selectCallback(); } - if (portalUrl.startsWith("/admin/configuration")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-configuration" - ); + }; + + ctrl.filter = function () { + ctrl.data = []; + ctrl.loadData(); + }; + ctrl.loadData = async function (pageIndex) { + if (pageIndex !== undefined) { + ctrl.request.pageIndex = pageIndex; } - if (portalUrl.startsWith("/admin/my-profile")) { - ctrl.trustedUrl = $sce.trustAsResourceUrl( - defaultUrl + "/basic-usage-users-profile" - ); + dataService.initDbName(ctrl.mixDbTableName); + ctrl.request.queries = []; + if (ctrl.queries) { + Object.keys(ctrl.queries).forEach((e) => { + if (ctrl.queries[e]) { + ctrl.request.queries.push({ + fieldName: e, + value: ctrl.queries[e], + compareOperator: "Like", + }); + } + }); } - - // switch (portalUrl) { - // case '/admin': - // default: - // ctrl.trustedUrl = $sce.trustAsResourceUrl(defaultUrl); - // break; - // } + var getData = await dataService.filter(ctrl.request); + ctrl.data = getData.data; + angular.forEach(ctrl.data.items, (e) => { + if (ctrl.selectedIds.find((n) => n.dataId == e.id)) { + e.isSelected = true; + } + }); + $scope.$apply(); + }; + ctrl.update = function (data) { + let url = `/admin/mix-db-data/details?dataContentId=${ + data.id + }&mixDbTableName=${ctrl.mixDbTableName}&mixDatabaseTitle=${ + ctrl.mixDatabaseTitle + }&parentId=${ctrl.parentId || ""}&parentName=${ + ctrl.parentName || "" + }&guidParentId=${ctrl.guidParentId || ""}`; + $location.url(url); }; }, ], @@ -15962,145 +16166,6 @@ modules.component("modalNavMetas", { ], }); -modules.component("modalNavDatas", { - templateUrl: "/mix-app/views/app-portal/components/modal-nav-datas/view.html", - bindings: { - fieldNames: "=", - mixDbTableId: "=?", - relationship: "=?", - mixDbTableName: "=?", - parentDatabaseName: "=?", - guidParentId: "=?", - parentId: "=?", - parentType: "=?", - type: "=?", - columnDisplay: "=?", - selectedIds: "=?", - selectedList: "=?", - selectCallback: "&?", - save: "&", - }, - controller: [ - "$rootScope", - "$scope", - "$location", - "$routeParams", - "ngAppSettings", - "RestMixAssociationPortalService", - "RestMixDbTablePortalService", - "MixDbDataService", - function ( - $rootScope, - $scope, - $location, - $routeParams, - ngAppSettings, - associationService, - databaseService, - dataService - ) { - var ctrl = this; - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.navs = []; - - ctrl.queries = {}; - ctrl.data = { items: [] }; - ctrl.$onInit = async function () { - ctrl.association = { - parentId: ctrl.parentId, - guidParentId: ctrl.guidParentId, - parentDatabaseName: ctrl.parentDatabaseName, - childDatabaseName: ctrl.mixDbTableName, - }; - dataService.initDbName(ctrl.mixDbTableName); - ctrl.request.sortBy = ctrl.fieldNames.id; - ctrl.request.name = ctrl.mixDbTableName; - ctrl.request.parentName = ctrl.parentName; - ctrl.request.relationship = ctrl.relationship; - // ctrl.request.parentId = ctrl.parentId; - if (!ctrl.database) { - var getDatabase = await databaseService.getByName( - ctrl.mixDbTableName - ); - if (getDatabase.success) { - ctrl.database = getDatabase.data; - $scope.$apply(); - } - } - if (!ctrl.data) { - await ctrl.loadData(); - } - }; - ctrl.showDbModel = function () { - $(`#modal-nav-data-${ctrl.mixDbTableName}`).modal("show"); - }; - ctrl.select = async (item) => { - $rootScope.isBusy = true; - if (item.isSelected && (ctrl.parentId || ctrl.guidParentId)) { - ctrl.association.childId = item.id; - let result = await dataService.createRelationship(ctrl.association); - if (result.success) { - item.associationId = result.data.id; - } - $rootScope.handleResponse(result); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - var nav = ctrl.selectedIds.find((m) => m.dataId == item.id); - let result = await dataService.deleteRelationship(nav.id); - $rootScope.handleResponse(result); - $rootScope.isBusy = false; - $scope.$apply(); - } - if (ctrl.selectCallback) { - ctrl.selectCallback(); - } - }; - - ctrl.filter = function () { - ctrl.data = []; - ctrl.loadData(); - }; - ctrl.loadData = async function (pageIndex) { - if (pageIndex !== undefined) { - ctrl.request.pageIndex = pageIndex; - } - dataService.initDbName(ctrl.mixDbTableName); - ctrl.request.queries = []; - if (ctrl.queries) { - Object.keys(ctrl.queries).forEach((e) => { - if (ctrl.queries[e]) { - ctrl.request.queries.push({ - fieldName: e, - value: ctrl.queries[e], - compareOperator: "Like", - }); - } - }); - } - var getData = await dataService.filter(ctrl.request); - ctrl.data = getData.data; - angular.forEach(ctrl.data.items, (e) => { - if (ctrl.selectedIds.find((n) => n.dataId == e.id)) { - e.isSelected = true; - } - }); - $scope.$apply(); - }; - ctrl.update = function (data) { - let url = `/admin/mix-db-data/details?dataContentId=${ - data.id - }&mixDbTableName=${ctrl.mixDbTableName}&mixDatabaseTitle=${ - ctrl.mixDatabaseTitle - }&parentId=${ctrl.parentId || ""}&parentName=${ - ctrl.parentName || "" - }&guidParentId=${ctrl.guidParentId || ""}`; - $location.url(url); - }; - }, - ], -}); - modules.component("modalNavPages", { templateUrl: "/mix-app/views/app-portal/components/modal-nav-pages/view.html", bindings: { @@ -16141,98 +16206,15 @@ modules.component("modalNavPages", { var item = { priority: e.priority, description: e.title, - pageId: e.id, - image: e.thumbnailUrl, - specificulture: e.specificulture, - status: "Published", - isActived: false, - }; - item[ctrl.srcField] = ctrl.srcId; - ctrl.navs.push(item); - }); - $rootScope.isBusy = false; - $scope.$apply(); - } else { - $rootScope.showErrors(response.errors); - $rootScope.isBusy = false; - $scope.$apply(); - } - }; - ctrl.saveSelected = function () { - ctrl.selected = $rootScope.filterArray( - ctrl.navs, - ["isActived"], - [true] - ); - setTimeout(() => { - ctrl.save().then(() => { - ctrl.loadPages(); - }); - }, 500); - }; - }, - ], -}); - -modules.component("modalNavPosts", { - templateUrl: - "/mix-app/views/app-portal/components/modal-nav-posts/modal-nav-posts.html", - bindings: { - srcColumn: "=", - srcId: "=", - query: "=", - selected: "=", - modelName: "=", - save: "&", - }, - controller: [ - "$rootScope", - "$scope", - "$routeParams", - "ngAppSettings", - "PostRestService", - function ($rootScope, $scope, $routeParams, ngAppSettings, postService) { - var ctrl = this; - ctrl.request = angular.copy(ngAppSettings.request); - ctrl.navs = []; - ctrl.associations = []; - ctrl.data = { items: [] }; - ctrl.loadPosts = async function (pageIndex) { - // ctrl.request.query = ctrl.query + ctrl.srcId; - if (pageIndex !== undefined) { - ctrl.request.pageIndex = pageIndex; - } - if (ctrl.request.fromDate !== null) { - var d = new Date(ctrl.request.fromDate); - ctrl.request.fromDate = d.toISOString(); - } - if (ctrl.request.toDate !== null) { - var d = new Date(ctrl.request.toDate); - ctrl.request.toDate = d.toISOString(); - } - if ($routeParams.type) { - ctrl.request.postType = $routeParams.type; - } else { - ctrl.request.postType = ""; - } - var response = await postService.getList(ctrl.request); - if (response.success) { - ctrl.data = response.data; - // ctrl.navs = []; - // angular.forEach(response.data.items, function (e) { - // var item = { - // priority: e.priority, - // description: e.title, - // postId: e.id, - // image: e.thumbnailUrl, - // specificulture: e.specificulture, - // post: e, - // status: "Published", - // isActived: false, - // }; - // item[ctrl.srcColumn] = ctrl.srcId; - // ctrl.navs.push(item); - // }); + pageId: e.id, + image: e.thumbnailUrl, + specificulture: e.specificulture, + status: "Published", + isActived: false, + }; + item[ctrl.srcField] = ctrl.srcId; + ctrl.navs.push(item); + }); $rootScope.isBusy = false; $scope.$apply(); } else { @@ -16241,9 +16223,6 @@ modules.component("modalNavPosts", { $scope.$apply(); } }; - ctrl.select = async (associations) => { - ctrl.associations = associations; - }; ctrl.saveSelected = function () { ctrl.selected = $rootScope.filterArray( ctrl.navs, @@ -16252,7 +16231,7 @@ modules.component("modalNavPosts", { ); setTimeout(() => { ctrl.save().then(() => { - ctrl.loadPosts(); + ctrl.loadPages(); }); }, 500); }; @@ -16392,6 +16371,101 @@ modules.component("modalNavs", { ], }); +modules.component("modalNavPosts", { + templateUrl: + "/mix-app/views/app-portal/components/modal-nav-posts/modal-nav-posts.html", + bindings: { + srcColumn: "=", + srcId: "=", + query: "=", + selected: "=", + modelName: "=", + save: "&", + }, + controller: [ + "$rootScope", + "$scope", + "$routeParams", + "ngAppSettings", + "PostRestService", + function ($rootScope, $scope, $routeParams, ngAppSettings, postService) { + var ctrl = this; + ctrl.request = angular.copy(ngAppSettings.request); + ctrl.navs = []; + ctrl.associations = []; + ctrl.data = { items: [] }; + ctrl.loadPosts = async function (pageIndex) { + // ctrl.request.query = ctrl.query + ctrl.srcId; + if (pageIndex !== undefined) { + ctrl.request.pageIndex = pageIndex; + } + if (ctrl.request.fromDate !== null) { + var d = new Date(ctrl.request.fromDate); + ctrl.request.fromDate = d.toISOString(); + } + if (ctrl.request.toDate !== null) { + var d = new Date(ctrl.request.toDate); + ctrl.request.toDate = d.toISOString(); + } + if ($routeParams.type) { + ctrl.request.postType = $routeParams.type; + } else { + ctrl.request.postType = ""; + } + var response = await postService.getList(ctrl.request); + if (response.success) { + ctrl.data = response.data; + // ctrl.navs = []; + // angular.forEach(response.data.items, function (e) { + // var item = { + // priority: e.priority, + // description: e.title, + // postId: e.id, + // image: e.thumbnailUrl, + // specificulture: e.specificulture, + // post: e, + // status: "Published", + // isActived: false, + // }; + // item[ctrl.srcColumn] = ctrl.srcId; + // ctrl.navs.push(item); + // }); + $rootScope.isBusy = false; + $scope.$apply(); + } else { + $rootScope.showErrors(response.errors); + $rootScope.isBusy = false; + $scope.$apply(); + } + }; + ctrl.select = async (associations) => { + ctrl.associations = associations; + }; + ctrl.saveSelected = function () { + ctrl.selected = $rootScope.filterArray( + ctrl.navs, + ["isActived"], + [true] + ); + setTimeout(() => { + ctrl.save().then(() => { + ctrl.loadPosts(); + }); + }, 500); + }; + }, + ], +}); + +modules.component("modalPermission", { + templateUrl: + "/mix-app/views/app-portal/components/modal-permission/modal-permission.html", + controller: "PermissionController", + bindings: { + message: "=", + }, +}); + modules.component("modalTemplate", { templateUrl: "/mix-app/views/app-portal/components/modal-template/view.html", controller: [ @@ -16434,15 +16508,6 @@ modules.component("modalTemplate", { ], }); -modules.component("modalPermission", { - templateUrl: - "/mix-app/views/app-portal/components/modal-permission/modal-permission.html", - controller: "PermissionController", - bindings: { - message: "=", - }, -}); - modules.component("monacoEditor", { templateUrl: "/mix-app/views/app-portal/components/monaco-editor/view.html", bindings: { @@ -16818,75 +16883,6 @@ modules.component("portalThemeSettings", { ], }); -modules.component("propertiesValue", { - templateUrl: - "/mix-app/views/app-portal/components/properties-value/view.html", - bindings: { - title: "=", - columns: "=", - properties: "=", - }, - controller: [ - "$rootScope", - "$scope", - function ($rootScope, $scope) { - var ctrl = this; - ctrl.defaultAttr = { - title: "", - name: "", - default: null, - options: [], - priority: 0, - dataType: 7, - isGroupBy: false, - isSelect: false, - isDisplay: true, - width: 3, - }; - ctrl.selectedProp = null; - ctrl.mixConfigurations = $rootScope.globalSettings; - - ctrl.$doCheck = function () { - if ( - angular.toJson(ctrl.columns) != angular.toJson(ctrl.trackedColumns) - ) { - ctrl.trackedColumns = angular.copy(ctrl.columns); - ctrl.trackedProperties = angular.copy(ctrl.properties); - ctrl.loadEditors(); - } - }.bind(ctrl); - - ctrl.loadEditors = function () { - ctrl.properties = []; - for (let i = 0; i < ctrl.columns.length; i++) { - var col = ctrl.columns[i]; - var oldObj = - $rootScope.findObjectByKey( - ctrl.trackedProperties, - "name", - col.systemName - ) || {}; - - ctrl.properties.push({ - title: col.displayName, - name: col.systemName, - dataType: col.dataType, - value: oldObj.value || col.defaultValue, - options: col.options, - }); - } - }; - - ctrl.addAttr = function () { - if (ctrl.columns) { - var t = angular.copy(ctrl.defaultAttr); - ctrl.columns.push(t); - } - }; - }, - ], -}); - modules.component("propertiesStructure", { templateUrl: "/mix-app/views/app-portal/components/properties-structure/view.html", @@ -17018,6 +17014,75 @@ modules.component("propertiesStructure", { }, }); +modules.component("propertiesValue", { + templateUrl: + "/mix-app/views/app-portal/components/properties-value/view.html", + bindings: { + title: "=", + columns: "=", + properties: "=", + }, + controller: [ + "$rootScope", + "$scope", + function ($rootScope, $scope) { + var ctrl = this; + ctrl.defaultAttr = { + title: "", + name: "", + default: null, + options: [], + priority: 0, + dataType: 7, + isGroupBy: false, + isSelect: false, + isDisplay: true, + width: 3, + }; + ctrl.selectedProp = null; + ctrl.mixConfigurations = $rootScope.globalSettings; + + ctrl.$doCheck = function () { + if ( + angular.toJson(ctrl.columns) != angular.toJson(ctrl.trackedColumns) + ) { + ctrl.trackedColumns = angular.copy(ctrl.columns); + ctrl.trackedProperties = angular.copy(ctrl.properties); + ctrl.loadEditors(); + } + }.bind(ctrl); + + ctrl.loadEditors = function () { + ctrl.properties = []; + for (let i = 0; i < ctrl.columns.length; i++) { + var col = ctrl.columns[i]; + var oldObj = + $rootScope.findObjectByKey( + ctrl.trackedProperties, + "name", + col.systemName + ) || {}; + + ctrl.properties.push({ + title: col.displayName, + name: col.systemName, + dataType: col.dataType, + value: oldObj.value || col.defaultValue, + options: col.options, + }); + } + }; + + ctrl.addAttr = function () { + if (ctrl.columns) { + var t = angular.copy(ctrl.defaultAttr); + ctrl.columns.push(t); + } + }; + }, + ], +}); + modules.component("serviceHubPortal", { templateUrl: "/mix-app/views/app-portal/components/service-hub-portal/view.html", diff --git a/src/applications/mixcore/wwwroot/mix-app/js/framework.min.js b/src/applications/mixcore/wwwroot/mix-app/js/framework.min.js index 486f466328..ae90d46092 100644 --- a/src/applications/mixcore/wwwroot/mix-app/js/framework.min.js +++ b/src/applications/mixcore/wwwroot/mix-app/js/framework.min.js @@ -1 +1 @@ -!function(e){"use strict";function t(e){if(!b(e))return Xn;$(e.objectMaxDepth)&&(Xn.objectMaxDepth=n(e.objectMaxDepth)?e.objectMaxDepth:NaN),$(e.urlErrorParamsEnabled)&&A(e.urlErrorParamsEnabled)&&(Xn.urlErrorParamsEnabled=e.urlErrorParamsEnabled)}function n(e){return x(e)&&0--n)return"...";var i,r=t.$$hashKey;if(C(e)){i=0;for(var o=e.length;i").append(e).html();try{return e[0].nodeType===wi?Jn(t):t.match(/^(<[^>]+>)/)[1].replace(/^<([\w-]+)/,function(e,t){return"<"+Jn(t)})}catch(e){return Jn(t)}}function W(e){try{return decodeURIComponent(e)}catch(e){}}function Y(e){var t={};return o((e||"").split("&"),function(e){var n,i,r;e&&(i=e=e.replace(/\+/g,"%20"),-1!==(n=e.indexOf("="))&&(i=e.substring(0,n),r=e.substring(n+1)),$(i=W(i))&&(r=!$(r)||W(r),Zn.call(t,i)?C(t[i])?t[i].push(r):t[i]=[t[i],r]:t[i]=r))}),t}function G(e){return X(e,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function X(e,t){return encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,t?"%20":"+")}function K(t,n){var i,r,a={};o(vi,function(e){e+="app",!i&&t.hasAttribute&&t.hasAttribute(e)&&(i=t,r=t.getAttribute(e))}),o(vi,function(e){var n;e+="app",!i&&(n=t.querySelector("["+e.replace(":","\\:")+"]"))&&(i=n,r=n.getAttribute(e))}),i&&($i?(a.strictDi=null!==function(e,t){var n,i,r=vi.length;for(i=0;i protocol indicates an extension, document.location.href does not match."))}function Z(t,n,i){b(i)||(i={}),i=u({strictDi:!1},i);var r=function(){if((t=Wn(t)).injector()){var r=t[0]===e.document?"document":B(t);throw oi("btstrpd",r.replace(//,">"))}return(n=n||[]).unshift(["$provide",function(e){e.value("$rootElement",t)}]),i.debugInfoEnabled&&n.push(["$compileProvider",function(e){e.debugInfoEnabled(!0)}]),n.unshift("ng"),(r=je(n,i.strictDi)).invoke(["$rootScope","$rootElement","$compile","$injector",function(e,t,n,i){e.$apply(function(){t.data("$injector",i),n(t)(e)})}]),r},a=/^NG_ENABLE_DEBUG_INFO!/,s=/^NG_DEFER_BOOTSTRAP!/;if(e&&a.test(e.name)&&(i.debugInfoEnabled=!0,e.name=e.name.replace(a,"")),e&&!s.test(e.name))return r();e.name=e.name.replace(s,""),ai.resumeBootstrap=function(e){return o(e,function(e){n.push(e)}),r()},D(ai.resumeDeferredBootstrap)&&ai.resumeDeferredBootstrap()}function J(){e.name="NG_ENABLE_DEBUG_INFO!"+e.name,e.location.reload()}function Q(e){if(!(e=ai.element(e).injector()))throw oi("test");return e.get("$$testability")}function ee(e,t){return t=t||"_",e.replace(bi,function(e,n){return(n?t:"")+e.toLowerCase()})}function te(){he.legacyXHTMLReplacement=!0}function ne(e,t,n){if(!e)throw oi("areq",t||"?",n||"required");return e}function ie(e,t,n){return n&&C(e)&&(e=e[e.length-1]),ne(D(e),t,"not a function, got "+(e&&"object"==typeof e?e.constructor.name||"Object":typeof e)),e}function re(e,t){if("hasOwnProperty"===e)throw oi("badname",t)}function oe(e){for(var t,n=e[0],i=e[e.length-1],r=1;n!==i&&(n=n.nextSibling);r++)(t||e[r]!==n)&&(t||(t=Wn(ei.call(e,0,r))),t.push(n));return t||e}function ae(){return Object.create(null)}function se(e){if(null==e)return"";switch(typeof e){case"string":break;case"number":e=""+e;break;default:e=!g(e)||C(e)||k(e)?L(e):e.toString()}return e}function le(e,t){if(C(e)){t=t||[];for(var n=0,i=e.length;n"):t,10>Bn)for(r=Ri[r]||Ri._default,i.innerHTML=r[1]+a+r[2],s=r[0];s--;)i=i.firstChild;else{for(s=(r=Pi[r]||[]).length;-1<--s;)i.appendChild(e.document.createElement(r[s])),i=i.firstChild;i.innerHTML=a}u=N(u,i.childNodes),(i=l.firstChild).textContent=""}else u.push(n.createTextNode(t));return l.textContent="",l.innerHTML="",o(u,function(e){l.appendChild(e)}),l}function he(t){if(t instanceof he)return t;var n,i;if(w(t)&&(t=pi(t),n=!0),!(this instanceof he)){if(n&&"<"!==t.charAt(0))throw Oi("nosel");return new he(t)}n?(n=e.document,De(this,t=(i=Ti.exec(t))?[n.createElement(i[1])]:(i=fe(t,n))?i.childNodes:[])):D(t)?Me(t):De(this,t)}function me(e){return e.cloneNode(!0)}function ge(e,t){!t&&pe(e)&&Wn.cleanData([e]),e.querySelectorAll&&Wn.cleanData(e.querySelectorAll("*"))}function ve(e){for(var t in e)return!1;return!0}function $e(e){var t,n=e.ng339,i=(t=n&&ki[n])&&t.events;(t=t&&t.data)&&!ve(t)||i&&!ve(i)||(delete ki[n],e.ng339=void 0)}function be(e,t,n,i){if($(i))throw Oi("offargs");var r=(i=we(e))&&i.events,a=i&&i.handle;if(a){if(t){var s=function(t){var i=r[t];$(n)&&P(i||[],n),$(n)&&i&&0c&&this.remove(f.key),t}},get:function(e){if(c").append(e).html())):n?ji.clone.call(e):e,l)for(var u in l)i.data("$"+u+"Controller",l[u].instance);return W.$$addScopeInfo(i,t),n&&n(i,t),o&&o(t,i,i,s),n||(e=o=null),i}}function Y(e,t,n,i,r,o){for(var a,s,l,u,c,d=[],p=C(e)||e instanceof Wn,f=0;fm.priority)break;if((w=m.scope)&&(m.templateUrl||(b(w)?(fe("new/isolated scope",S||k,m,R),S=m):fe("new/isolated scope",S,m,R)),k=k||m),g=m.name,!N&&(m.replace&&(m.templateUrl||m.template)||m.transclude&&!m.$$tlb)){for(w=L+1;N=t[w++];)if(N.transclude&&!N.$$tlb||N.replace&&(N.templateUrl||N.template)){j=!0;break}N=!0}if(!m.templateUrl&&m.controller&&(E=E||ae(),fe("'"+g+"' controller",E[g],m,R),E[g]=m),w=m.transclude)if(M=!0,m.$$tlb||(fe("transclusion",A,m,R),A=m),"element"===w)I=!0,x=m.priority,$=R,R=i.$$element=Wn(W.$$createComment(g,i[g])),n=R[0],ye(s,ei.call($,0),n),F=te(j,$,a,x,l&&l.name,{nonTlbTranscludeDirective:A});else{var Y=ae();if(b(w)){$=e.document.createDocumentFragment();var G=ae(),X=ae();for(var Z in o(w,function(e,t){var n="?"===e.charAt(0);e=n?e.substring(1):e,G[e]=t,Y[t]=null,X[t]=n}),o(R.contents(),function(t){var n=G[Ge(_(t))];n?(X[n]=!0,Y[n]=Y[n]||e.document.createDocumentFragment(),Y[n].appendChild(t)):$.appendChild(t)}),o(X,function(e,t){if(!e)throw or("reqslot",t)}),Y)Y[Z]&&(F=Wn(Y[Z].childNodes),Y[Z]=te(j,F,a));$=Wn($.childNodes)}else $=Wn(me(n)).contents();R.empty(),(F=te(j,$,a,void 0,void 0,{needsNewScope:m.$$isolateScope||m.$$newScope})).$$slots=Y}if(m.template)if(P=!0,fe("template",O,m,R),O=m,w=D(m.template)?m.template(R,i):m.template,w=Ie(w),m.replace){if(l=m,$=Ai.test(w)?Ke(ge(m.templateNamespace,pi(w))):[],n=$[0],1!==$.length||1!==n.nodeType)throw or("tplrt",g,"");ye(s,R,n),w=K(n,[],H={$attr:{}});var ee=t.splice(L+1,t.length-(L+1));(S||k)&&se(w,S,k),t=t.concat(w).concat(ee),ce(i,H),H=t.length}else R.html(w);if(m.templateUrl)P=!0,fe("template",O,m,R),O=m,m.replace&&(l=m),h=de(t.splice(L,t.length-L),R,i,s,M&&F,c,d,{controllerDirectives:E,newScopeDirective:k!==m&&k,newIsolateScopeDirective:S,templateDirective:O,nonTlbTranscludeDirective:A}),H=t.length;else if(m.compile)try{y=m.compile(R,i,F);var ne=m.$$originalDirective||m;D(y)?f(null,U(ne,y),V,q):y&&f(U(ne,y.pre),U(ne,y.post),V,q)}catch(e){r(e,B(R))}m.terminal&&(h.terminal=!0,x=Math.max(x,m.priority))}return h.scope=k&&!0===k.scope,h.transcludeOnThisElement=M,h.templateOnThisElement=P,h.transclude=F,p.hasElementTranscludeDirective=I,h}function re(e,t,n,i){var r;if(w(t)){var a=t.match(g);t=t.substring(a[0].length);var s=a[1]||a[3];a="?"===a[2];if("^^"===s?n=n.parent():r=(r=i&&i[t])&&r.instance,!r){var l="$"+t+"Controller";r="^^"===s&&n[0]&&9===n[0].nodeType?null:s?n.inheritedData(l):n.data(l)}if(!r&&!a)throw or("ctreq",t,e)}else if(C(t))for(r=[],s=0,a=t.length;sn.priority)&&-1!==n.restrict.indexOf(r)){if(l&&(n=p(n,{$$start:l,$$end:u})),!n.$$bindings){var h=c=n,m=n.name,g={isolateScope:null,bindToController:null};if(b(h.scope)&&(!0===h.bindToController?(g.bindToController=i(h.scope,m,!0),g.isolateScope={}):g.isolateScope=i(h.scope,m,!1)),b(h.bindToController)&&(g.bindToController=i(h.bindToController,m,!0)),g.bindToController&&!h.controller)throw or("noctrl",m);b((c=c.$$bindings=g).isolateScope)&&(n.$$isolateBindings=c.isolateScope)}e.push(n),c=n}return c}function ue(e){if(a.hasOwnProperty(e))for(var n=t.get(e+"Directive"),i=0,r=n.length;i"+n+"",i.childNodes[0].childNodes;default:return n}}function ve(e){return V(j.valueOf(e),"ng-prop-srcset")}function $e(e,t,n,i){if(y.test(i))throw or("nodomevents");var r=function(e,t){var n=t.toLowerCase();return N[e+"|"+n]||N["*|"+n]}(e=_(e),i),o=h;"srcset"!==i||"img"!==e&&"source"!==e?r&&(o=j.getTrusted.bind(j,r)):o=ve,t.push({priority:100,compile:function(e,t){var r=m(t[n]),a=m(t[n],function(e){return j.valueOf(e)});return{pre:function(e,t){function n(){var n=r(e);t[0][i]=o(n)}n(),e.$watch(a,n)}}}})}function be(e,t,i,r,o){var a=_(e),s=function(e,t){return"srcdoc"===t?j.HTML:"src"===t||"ngSrc"===t?-1===["img","video","audio","source","track"].indexOf(e)?j.RESOURCE_URL:j.MEDIA_URL:"xlinkHref"===t?"image"===e?j.MEDIA_URL:"a"===e?j.URL:j.RESOURCE_URL:"form"===e&&"action"===t||"base"===e&&"href"===t||"link"===e&&"href"===t?j.RESOURCE_URL:"a"!==e||"href"!==t&&"ngHref"!==t?void 0:j.URL}(a,r),l=d[r]||o,u=n(i,!o,s,l);if(u){if("multiple"===r&&"select"===a)throw or("selmulti",B(e));if(y.test(r))throw or("nodomevents");t.push({priority:100,compile:function(){return{pre:function(e,t,o){t=o.$$observers||(o.$$observers=ae());var a=o[r];a!==i&&(u=a&&n(a,!0,s,l),i=a),u&&(o[r]=u(e),(t[r]||(t[r]=[])).$$inter=!0,(o.$$observers&&o.$$observers[r].$$scope||e).$watch(u,function(e,t){"class"===r&&e!==t?o.$updateClass(e,t):o.$set(r,e)}))}}}})}}function ye(t,n,i){var r,o,a=n[0],s=n.length,l=a.parentNode;if(t)for(r=0,o=t.length;r";var i=(t=Se.firstChild.attributes)[0];t.removeNamedItem(i.name),i.value=n,e.attributes.setNamedItem(i)}(this.$$element[0],i,t)),(e=this.$$observers)&&o(e[l],function(e){try{e(t)}catch(e){r(e)}})},$observe:function(e,t){var n=this,i=n.$$observers||(n.$$observers=ae()),r=i[e]||(i[e]=[]);return r.push(t),x.$evalAsync(function(){r.$$inter||!n.hasOwnProperty(e)||v(n[e])||t(n[e])}),function(){P(r,t)}}};var Me=n.startSymbol(),Pe=n.endSymbol(),Ie="{{"===Me&&"}}"===Pe?h:function(e){return e.replace(/\{\{/g,Me).replace(/}}/g,Pe)},Re=/^ng(Attr|Prop|On)([A-Z].*)$/,Fe=/^(.+)Start$/;return W.$$addBindingInfo=k?function(e,t){var n=e.data("$binding")||[];C(t)?n=n.concat(t):n.push(t),e.data("$binding",n)}:f,W.$$addBindingClass=k?function(e){q(e,"ng-binding")}:f,W.$$addScopeInfo=k?function(e,t,n,i){e.data(n?i?"$isolateScopeNoTemplate":"$isolateScope":"$scope",t)}:f,W.$$addScopeClass=k?function(e,t){q(e,t?"ng-isolate-scope":"ng-scope")}:f,W.$$createComment=function(t,n){var i="";return k&&(i=" "+(t||"")+": ",n&&(i+=n+" ")),e.document.createComment(i)},W}]}function Ye(e,t){this.previousValue=e,this.currentValue=t}function Ge(e){return e.replace(sr,"").replace(lr,function(e,t,n){return n?t.toUpperCase():t})}function Xe(e,t){var n="",i=e.split(/\s+/),r=t.split(/\s+/),o=0;e:for(;o=t)return e;for(;t--;){var n=e[t];(8===n.nodeType||n.nodeType===wi&&""===n.nodeValue.trim())&&ti.call(e,t,1)}return e}function Ze(){var e={};this.has=function(t){return e.hasOwnProperty(t)},this.register=function(t,n){re(t,"controller"),b(t)?u(e,t):e[t]=n},this.$get=["$injector",function(t){function n(e,t,n,r){if(!e||!b(e.$scope))throw i("$controller")("noscp",r,t);e.$scope[t]=n}return function(i,r,o,a){var s,l,c;if(o=!0===o,a&&w(a)&&(c=a),w(i)){if(!(a=i.match(cr)))throw ur("ctrlfmt",i);if(l=a[1],c=c||a[3],!(i=e.hasOwnProperty(l)?e[l]:function(e,t,n){if(!t)return e;for(var i,r=e,o=(t=t.split(".")).length,a=0;ae?t:p.reject(t)}if(!b(t))throw i("$http")("badreq",t);if(!w(m.valueOf(t.url)))throw i("$http")("badreq",t.url);var s=u({method:"get",transformRequest:e.transformRequest,transformResponse:e.transformResponse,paramSerializer:e.paramSerializer,jsonpCallbackParam:e.jsonpCallbackParam},t);s.headers=function(t){var n,i,r,a=e.headers,s=u({},t.headers);a=u({},a.common,a[Jn(t.method)]);e:for(n in a){for(r in i=Jn(n),s)if(Jn(r)===i)continue e;s[n]=a[n]}return function(e,t){var n,i={};return o(e,function(e,r){D(e)?null!=(n=e(t))&&(i[r]=n):i[r]=e}),i}(s,le(t))}(t),s.method=Qn(s.method),s.paramSerializer=w(s.paramSerializer)?h.get(s.paramSerializer):s.paramSerializer,a.$$incOutstandingRequestCount("$http");var l=[],c=[];return t=p.resolve(s),o(k,function(e){(e.request||e.requestError)&&l.unshift(e.request,e.requestError),(e.response||e.responseError)&&c.push(e.response,e.responseError)}),t=(t=n(t,l)).then(function(t){var n=t.headers,i=st(t.data,at(n),void 0,t.transformRequest);return v(i)&&o(n,function(e,t){"content-type"===Jn(t)&&delete n[t]}),v(t.withCredentials)&&!v(e.withCredentials)&&(t.withCredentials=e.withCredentials),y(t,i).then(r,r)}),(t=n(t,c)).finally(function(){a.$$completeOutstandingRequest(f,"$http")})}function y(n,i){function r(e){if(e){var n={};return o(e,function(e,i){n[i]=function(n){function i(){e(n)}t?d.$applyAsync(i):d.$$phase?i():d.$apply(i)}}),n}}function a(e,t,i,r,o){(200<=(t=-1<=t?t:0)&&300>t?y.resolve:y.reject)({data:e,status:t,headers:at(i),config:n,statusText:r,xhrStatus:o})}function u(e){a(e.data,e.status,le(e.headers()),e.statusText,e.xhrStatus)}function c(){var e=g.pendingRequests.indexOf(n);-1!==e&&g.pendingRequests.splice(e,1)}var f,h,y=p.defer(),k=y.promise,S=n.headers,O="jsonp"===Jn(n.method),T=n.url;return O?T=m.getTrustedResourceUrl(T):w(T)||(T=m.valueOf(T)),T=function(e,t){return 0e?f.put(T,[e,n,ot(i),r,o]):f.remove(T)),t?d.$applyAsync(s):(s(),d.$$phase||d.$apply())},S,n.timeout,n.withCredentials,n.responseType,r(n.eventHandlers),r(n.uploadEventHandlers))),k}var x=c("$http");e.paramSerializer=w(e.paramSerializer)?h.get(e.paramSerializer):e.paramSerializer;var k=[];o(n,function(e){k.unshift(w(e)?h.get(e):h.invoke(e))});var E=function(e){var t=[Lr].concat(e.map(Jt));return function(e){return e=Jt(e),t.some(Qt.bind(null,e))}}(r);return g.pendingRequests=[],function(e){o(arguments,function(e){g[e]=function(t,n){return g(u({},n||{},{method:e,url:t}))}})}("get","delete","head","jsonp"),function(e){o(arguments,function(e){g[e]=function(t,n,i){return g(u({},i||{},{method:e,url:t,data:n}))}})}("post","put","patch"),g.defaults=e,g}]}function ut(){this.$get=function(){return function(){return new e.XMLHttpRequest}}}function ct(){this.$get=["$browser","$jsonpCallbacks","$document","$xhrFactory",function(e,t,n,i){return function(e,t,n,i,r){function a(e,t,n){e=e.replace("JSON_CALLBACK",t);var o=r.createElement("script"),a=null;return o.type="text/javascript",o.src=e,o.async=!0,a=function(e){o.removeEventListener("load",a),o.removeEventListener("error",a),r.body.removeChild(o),o=null;var s=-1,l="unknown";e&&("load"!==e.type||i.wasCalled(t)||(e={type:"error"}),l=e.type,s="error"===e.type?404:200),n&&n(s,l)},o.addEventListener("load",a),o.addEventListener("error",a),r.body.appendChild(o),a}return function(r,s,l,u,c,d,p,f,h,m){function g(e){k="timeout"===e,w&&w(),x&&x.abort()}function b(e,t,i,r,o,a){$(C)&&n.cancel(C),w=x=null,e(t,i,r,o,a)}if(s=s||e.url(),"jsonp"===Jn(r))var y=i.createCallback(s),w=a(s,y,function(e,t){var n=200===e&&i.getResponse(y);b(u,e,n,"",t,"complete"),i.removeCallback(y)});else{var x=t(r,s),k=!1;if(x.open(r,s,!0),o(c,function(e,t){$(e)&&x.setRequestHeader(t,e)}),x.onload=function(){var e=x.statusText||"",t="response"in x?x.response:x.responseText,n=1223===x.status?204:x.status;0===n&&(n=t?200:"file"===Jt(s).protocol?404:0),b(u,n,t,x.getAllResponseHeaders(),e,"complete")},x.onerror=function(){b(u,-1,null,null,"","error")},x.ontimeout=function(){b(u,-1,null,null,"","timeout")},x.onabort=function(){b(u,-1,null,null,"",k?"timeout":"abort")},o(h,function(e,t){x.addEventListener(t,e)}),o(m,function(e,t){x.upload.addEventListener(t,e)}),p&&(x.withCredentials=!0),f)try{x.responseType=f}catch(e){if("json"!==f)throw e}x.send(v(l)?null:l)}if(0=l&&(m.resolve(f),o(g.$$intervalId)),h||i.$apply()},s,m,h),g}}}]}function ht(e,t){var n=Jt(e);t.$$protocol=n.protocol,t.$$host=n.hostname,t.$$port=d(n.port)||xr[n.protocol]||null}function mt(e,t,n){if(Cr.test(e))throw kr("badpath",e);(i="/"!==e.charAt(0))&&(e="/"+e),e=Jt(e);for(var i,r=(i=(i&&"/"===e.pathname.charAt(0)?e.pathname.substring(1):e.pathname).split("/")).length;r--;)i[r]=decodeURIComponent(i[r]),n&&(i[r]=i[r].replace(/\//g,"%2F"));n=i.join("/"),t.$$path=n,t.$$search=Y(e.search),t.$$hash=decodeURIComponent(e.hash),t.$$path&&"/"!==t.$$path.charAt(0)&&(t.$$path="/"+t.$$path)}function gt(e,t){return e.slice(0,t.length)===t}function vt(e,t){if(gt(t,e))return t.substr(e.length)}function $t(e){var t=e.indexOf("#");return-1===t?e:e.substr(0,t)}function bt(e,t,n){this.$$html5=!0,n=n||"",ht(e,this),this.$$parse=function(e){var n=vt(t,e);if(!w(n))throw kr("ipthprfx",e,t);mt(n,this,!0),this.$$path||(this.$$path="/"),this.$$compose()},this.$$normalizeUrl=function(e){return t+e.substr(1)},this.$$parseLinkUrl=function(i,r){return r&&"#"===r[0]?(this.hash(r.slice(1)),!0):($(o=vt(e,i))?(a=o,a=n&&$(o=vt(n,o))?t+(vt("/",o)||o):e+a):$(o=vt(t,i))?a=t+o:t===i+"/"&&(a=t),a&&this.$$parse(a),!!a);var o,a}}function yt(e,t,n){ht(e,this),this.$$parse=function(i){var r;v(o=vt(e,i)||vt(t,i))||"#"!==o.charAt(0)?this.$$html5?r=o:(r="",v(o)&&(e=i,this.replace())):v(r=vt(n,o))&&(r=o),mt(r,this,!1),i=this.$$path;var o,a=/^\/[A-Z]:(\/.*)/;gt(r,o=e)&&(r=r.replace(o,"")),a.exec(r)||(i=(r=a.exec(i))?r[1]:i),this.$$path=i,this.$$compose()},this.$$normalizeUrl=function(t){return e+(t?n+t:"")},this.$$parseLinkUrl=function(t,n){return $t(e)===$t(t)&&(this.$$parse(t),!0)}}function wt(e,t,n){this.$$html5=!0,yt.apply(this,arguments),this.$$parseLinkUrl=function(i,r){return r&&"#"===r[0]?(this.hash(r.slice(1)),!0):(e===$t(i)?o=i:(a=vt(t,i))?o=e+n+a:t===i+"/"&&(o=t),o&&this.$$parse(o),!!o);var o,a},this.$$normalizeUrl=function(t){return e+n+t}}function xt(e){return function(){return this[e]}}function kt(e,t){return function(n){return v(n)?this[e]:(this[e]=t(n),this.$$compose(),this)}}function Ct(){var e="!",t={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(t){return $(t)?(e=t,this):e},this.html5Mode=function(e){return A(e)?(t.enabled=e,this):b(e)?(A(e.enabled)&&(t.enabled=e.enabled),A(e.requireBase)&&(t.requireBase=e.requireBase),(A(e.rewriteLinks)||w(e.rewriteLinks))&&(t.rewriteLinks=e.rewriteLinks),this):t},this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(n,i,r,o,a){function s(e,t,n){var r=u.url(),o=u.$$state;try{i.url(e,t,n),u.$$state=i.state()}catch(e){throw u.url(r),u.$$state=o,e}}function l(e,t){n.$broadcast("$locationChangeSuccess",u.absUrl(),e,u.$$state,t)}var u,c;c=i.baseHref();var d,p=i.url();if(t.enabled){if(!c&&t.requireBase)throw kr("nobase");d=p.substring(0,p.indexOf("/",p.indexOf("//")+2))+(c||"/"),c=r.history?bt:wt}else d=$t(p),c=yt;var f=d.substr(0,$t(d).lastIndexOf("/")+1);(u=new c(d,f,"#"+e)).$$parseLinkUrl(p,p),u.$$state=i.state();var h=/^\s*(javascript|mailto):/i;o.on("click",function(e){if((a=t.rewriteLinks)&&!e.ctrlKey&&!e.metaKey&&!e.shiftKey&&2!==e.which&&2!==e.button){for(var r=Wn(e.target);"a"!==_(r[0]);)if(r[0]===o[0]||!(r=r.parent())[0])return;if(!w(a)||!v(r.attr(a))){var a=r.prop("href"),s=r.attr("href")||r.attr("xlink:href");b(a)&&"[object SVGAnimatedString]"===a.toString()&&(a=Jt(a.animVal).href),h.test(a)||!a||r.attr("target")||e.isDefaultPrevented()||!u.$$parseLinkUrl(a,s)||(e.preventDefault(),u.absUrl()!==i.url()&&n.$apply())}}}),u.absUrl()!==p&&i.url(u.absUrl(),!0);var m=!0;return i.onUrlChange(function(e,t){gt(e,f)?(n.$evalAsync(function(){var i,r=u.absUrl(),o=u.$$state;u.$$parse(e),u.$$state=t,i=n.$broadcast("$locationChangeStart",e,r,t,o).defaultPrevented,u.absUrl()===e&&(i?(u.$$parse(r),u.$$state=o,s(r,!1,o)):(m=!1,l(r,o)))}),n.$$phase||n.$digest()):a.location.href=e}),n.$watch(function(){if(m||u.$$urlUpdatedByLocation){u.$$urlUpdatedByLocation=!1;var e=i.url(),t=u.absUrl(),o=i.state(),a=u.$$replace,c=!function(e,t){return e===t||Jt(e).href===Jt(t).href}(e,t)||u.$$html5&&r.history&&o!==u.$$state;(m||c)&&(m=!1,n.$evalAsync(function(){var t=u.absUrl(),i=n.$broadcast("$locationChangeStart",t,e,u.$$state,o).defaultPrevented;u.absUrl()===t&&(i?(u.$$parse(e),u.$$state=o):(c&&s(t,a,o===u.$$state?null:u.$$state),l(e,o)))}))}u.$$replace=!1}),u}]}function Et(){var e=!0,t=this;this.debugEnabled=function(t){return $(t)?(e=t,this):e},this.$get=["$window",function(n){function i(e){var t=n.console||{},i=t[e]||t.log||f;return function(){var e=[];return o(arguments,function(t){e.push(function(e){return E(e)&&(e.stack&&r?e=e.message&&-1===e.stack.indexOf(e.message)?"Error: "+e.message+"\n"+e.stack:e.stack:e.sourceURL&&(e=e.message+"\n"+e.sourceURL+":"+e.line)),e}(t))}),Function.prototype.apply.call(i,t,e)}}var r=Bn||/\bEdge\//.test(n.navigator&&n.navigator.userAgent);return{log:i("log"),info:i("info"),warn:i("warn"),error:i("error"),debug:function(){var n=i("debug");return function(){e&&n.apply(t,arguments)}}()}}]}function Dt(e){return e+""}function St(e,t){return void 0!==e?e:t}function Ot(e,t){return void 0===e?t:void 0===t?e:e+t}function Tt(e,t,n){var i,r,a=e.isPure=function(e,t){switch(e.type){case Mr.MemberExpression:if(e.computed)return!1;break;case Mr.UnaryExpression:return 1;case Mr.BinaryExpression:return"+"!==e.operator&&1;case Mr.CallExpression:return!1}return void 0===t?_r:t}(e,n);switch(e.type){case Mr.Program:i=!0,o(e.body,function(e){Tt(e.expression,t,a),i=i&&e.expression.constant}),e.constant=i;break;case Mr.Literal:e.constant=!0,e.toWatch=[];break;case Mr.UnaryExpression:Tt(e.argument,t,a),e.constant=e.argument.constant,e.toWatch=e.argument.toWatch;break;case Mr.BinaryExpression:Tt(e.left,t,a),Tt(e.right,t,a),e.constant=e.left.constant&&e.right.constant,e.toWatch=e.left.toWatch.concat(e.right.toWatch);break;case Mr.LogicalExpression:Tt(e.left,t,a),Tt(e.right,t,a),e.constant=e.left.constant&&e.right.constant,e.toWatch=e.constant?[]:[e];break;case Mr.ConditionalExpression:Tt(e.test,t,a),Tt(e.alternate,t,a),Tt(e.consequent,t,a),e.constant=e.test.constant&&e.alternate.constant&&e.consequent.constant,e.toWatch=e.constant?[]:[e];break;case Mr.Identifier:e.constant=!1,e.toWatch=[e];break;case Mr.MemberExpression:Tt(e.object,t,a),e.computed&&Tt(e.property,t,a),e.constant=e.object.constant&&(!e.computed||e.property.constant),e.toWatch=e.constant?[]:[e];break;case Mr.CallExpression:i=n=!!e.filter&&!t(e.callee.name).$stateful,r=[],o(e.arguments,function(e){Tt(e,t,a),i=i&&e.constant,r.push.apply(r,e.toWatch)}),e.constant=i,e.toWatch=n?r:[e];break;case Mr.AssignmentExpression:Tt(e.left,t,a),Tt(e.right,t,a),e.constant=e.left.constant&&e.right.constant,e.toWatch=[e];break;case Mr.ArrayExpression:i=!0,r=[],o(e.elements,function(e){Tt(e,t,a),i=i&&e.constant,r.push.apply(r,e.toWatch)}),e.constant=i,e.toWatch=r;break;case Mr.ObjectExpression:i=!0,r=[],o(e.properties,function(e){Tt(e.value,t,a),i=i&&e.value.constant,r.push.apply(r,e.value.toWatch),e.computed&&(Tt(e.key,t,!1),i=i&&e.key.constant,r.push.apply(r,e.key.toWatch))}),e.constant=i,e.toWatch=r;break;case Mr.ThisExpression:e.constant=!1,e.toWatch=[];break;case Mr.LocalsExpression:e.constant=!1,e.toWatch=[]}}function At(e){if(1===e.length){var t=(e=e[0].expression).toWatch;return 1!==t.length?t:t[0]!==e?t:void 0}}function Mt(e){return e.type===Mr.Identifier||e.type===Mr.MemberExpression}function _t(e){if(1===e.body.length&&Mt(e.body[0].expression))return{type:Mr.AssignmentExpression,left:e.body[0].expression,right:{type:Mr.NGValueParameter},operator:"="}}function Pt(e){this.$filter=e}function It(e){this.$filter=e}function Rt(e,t,n){this.ast=new Mr(e,n),this.astCompiler=n.csp?new It(t):new Pt(t)}function Ft(e){return D(e.valueOf)?e.valueOf():Sr.call(e)}function Nt(){var e,t,n=ae(),i={true:!0,false:!1,null:null,undefined:void 0};this.addLiteral=function(e,t){i[e]=t},this.setIdentifierFns=function(n,i){return e=n,t=i,this},this.$get=["$filter",function(r){function a(e,t){var i,o;switch(typeof e){case"string":return o=e=e.trim(),(i=n[o])||(i=new Rt(i=new Ar(g),r,g).parse(e),n[o]=p(i)),m(i,t);case"function":return m(e,t);default:return m(f,t)}}function s(e,t,n){return null==e||null==t?e===t:!("object"==typeof e&&(e=Ft(e),"object"==typeof e&&!n))&&(e===t||e!=e&&t!=t)}function l(e,t,n,i,r){var o;if(1===(l=i.inputs).length){var a=s,l=l[0];return e.$watch(function(e){var t=l(e);return s(t,a,l.isPure)||(o=i(e,void 0,void 0,[t]),a=t&&Ft(t)),o},t,n,r)}for(var u=[],c=[],d=0,p=l.length;d=n.$$state.status&&r&&r.length&&e(function(){for(var e,n,o=0,a=r.length;oe)for(t in c++,o)Zn.call(i,t)||(m--,delete o[t])}else o!==i&&(o=i,c++);return c}}n.$$pure=s(e).literal,n.$stateful=!n.$$pure;var i,o,a,l=this,u=1v&&(x[f=4-v]||(x[f]=[]),x[f].push({msg:D(r.exp)?"fn: "+(r.exp.name||r.exp.toString()):r.exp,newVal:o,oldVal:s}))}catch(e){i(e)}if(!(u=!p.$$suspended&&p.$$watchersCount&&p.$$childHead||p!==b&&p.$$nextSibling))for(;p!==b&&!(u=p.$$nextSibling);)p=p.$parent}while(p=u);if((c||y.length)&&!v--)throw $.$$phase=null,t("infdig",e,x)}while(c||y.length);for($.$$phase=null;kBn)throw Ir("iequirks");var i=le(Rr);i.isEnabled=function(){return e},i.trustAs=n.trustAs,i.getTrusted=n.getTrusted,i.valueOf=n.valueOf,e||(i.trustAs=i.getTrusted=function(e,t){return t},i.valueOf=h),i.parseAs=function(e,n){var r=t(n);return r.literal&&r.constant?r:t(n,function(t){return i.getTrusted(e,t)})};var r=i.parseAs,a=i.getTrusted,s=i.trustAs;return o(Rr,function(e,t){var n=Jn(t);i[("parse_as_"+n).replace(Fr,ce)]=function(t){return r(e,t)},i[("get_trusted_"+n).replace(Fr,ce)]=function(t){return a(e,t)},i[("trust_as_"+n).replace(Fr,ce)]=function(t){return s(e,t)}}),i}]}function Yt(){this.$get=["$window","$document",function(e,t){var n={},i=!((!e.nw||!e.nw.process)&&e.chrome&&(e.chrome.app&&e.chrome.app.runtime||!e.chrome.app&&e.chrome.runtime&&e.chrome.runtime.id))&&e.history&&e.history.pushState,r=d((/android (\d+)/.exec(Jn((e.navigator||{}).userAgent))||[])[1]),o=/Boxee/i.test((e.navigator||{}).userAgent),a=t[0]||{},s=a.body&&a.body.style,l=!1,u=!1;return s&&(l=!!("transition"in s||"webkitTransition"in s),u=!!("animation"in s||"webkitAnimation"in s)),{history:!(!i||4>r||o),hasEvent:function(e){if("input"===e&&Bn)return!1;if(v(n[e])){var t=a.createElement("div");n[e]="on"+e in t}return n[e]},csp:hi(),transitions:l,animations:u,android:r}}]}function Gt(){this.$get=m(function(e){return new function(e){function t(){var e=r.pop();return e&&e.cb}function n(e){for(var t=r.length-1;0<=t;--t){var n=r[t];if(n.type===e)return r.splice(t,1),n.cb}}var i={},r=[],o=this.ALL_TASKS_TYPE="$$all$$",a=this.DEFAULT_TASK_TYPE="$$default$$";this.completeTask=function(r,s){s=s||a;try{r()}finally{var l;i[l=s||a]&&(i[l]--,i[o]--),l=i[s];var u=i[o];if(!u||!l)for(l=u?n:t;u=l(s);)try{u()}catch(t){e.error(t)}}},this.incTaskCount=function(e){i[e=e||a]=(i[e]||0)+1,i[o]=(i[o]||0)+1},this.notifyWhenNoPendingTasks=function(e,t){i[t=t||o]?r.push({type:t,cb:e}):e()}}(e)})}function Xt(){var e;this.httpOptions=function(t){return t?(e=t,this):e},this.$get=["$exceptionHandler","$templateCache","$http","$q","$sce",function(t,n,i,r,o){function a(s,l){a.totalPendingRequests++,w(s)&&!v(n.get(s))||(s=o.getTrustedResourceUrl(s));var c=i.defaults&&i.defaults.transformResponse;return C(c)?c=c.filter(function(e){return e!==rt}):c===rt&&(c=null),i.get(s,u({cache:n,transformResponse:c},e)).finally(function(){a.totalPendingRequests--}).then(function(e){return n.put(s,e.data)},function(e){return l||(e=Nr("tpload",s,e.status,e.statusText),t(e)),r.reject(e)})}return a.totalPendingRequests=0,a}]}function Kt(){this.$get=["$rootScope","$browser","$location",function(e,t,n){return{findBindings:function(e,t,n){var i=[];return o(e=e.getElementsByClassName("ng-binding"),function(e){var r=ai.element(e).data("$binding");r&&o(r,function(r){n?new RegExp("(^|\\s)"+fi(t)+"(\\s|\\||$)").test(r)&&i.push(e):-1!==r.indexOf(t)&&i.push(e)})}),i},findModels:function(e,t,n){for(var i=["ng-","data-ng-","ng\\:"],r=0;rn-1){for(i=0;i>n;i--)r.unshift(0),e.i++;r.unshift(1),e.i++}else r[n-1]++;for(;on&&(n=i),n+=+e.slice(i+1),e=e.substring(0,i)):0>n&&(n=e.length),i=0;e.charAt(i)===qr;i++);if(i===(o=e.length))t=[0],n=1;else{for(o--;e.charAt(o)===qr;)o--;for(n-=i,t=[],r=0;i<=o;i++,r++)t[r]=+e.charAt(i)}return n>Vr&&(t=t.splice(0,Vr-1),a=n-1,n=1),{d:t,e:a,i:n}}(s),r,t.minFrac,t.maxFrac),l=a.d,s=a.i,r=a.e,o=[],a=l.reduce(function(e,t){return e&&!t},!0);0>s;)l.unshift(0),s++;for(0=t.lgSize&&s.unshift(l.splice(-t.lgSize,l.length).join(""));l.length>t.gSize;)s.unshift(l.splice(-t.gSize,l.length).join(""));l.length&&s.unshift(l.join("")),l=s.join(n),o.length&&(l+=i+o.join("")),r&&(l+="e+"+r)}return 0>e&&!a?t.negPre+l+t.negSuf:t.posPre+l+t.posSuf}function dn(e,t,n,i){var r="";for((0>e||i&&0>=e)&&(i?e=1-e:(e=-e,r="-")),e=""+e;e.length-n)&&(o+=n),0===o&&-12===n&&(o=12),dn(o,t,i,r)}}function fn(e,t,n){return function(i,r){var o=i["get"+e]();return r[Qn((n?"STANDALONE":"")+(t?"SHORT":"")+e)][o]}}function hn(e){var t=new Date(e,0,1).getDay();return new Date(e,0,(4>=t?5:12)-t)}function mn(e){return function(t){var n=hn(t.getFullYear());return t=+new Date(t.getFullYear(),t.getMonth(),t.getDate()+(4-t.getDay()))-+n,dn(t=1+Math.round(t/6048e5),e)}}function gn(e,t){return 0>=e.getFullYear()?t.ERAS[0]:t.ERAS[1]}function vn(e){function t(e){var t;if(t=e.match(n)){e=new Date(0);var i=0,r=0,o=t[8]?e.setUTCFullYear:e.setFullYear,a=t[8]?e.setUTCHours:e.setHours;t[9]&&(i=d(t[9]+t[10]),r=d(t[9]+t[11])),o.call(e,d(t[1]),d(t[2])-1,d(t[3])),i=d(t[4]||0)-i,r=d(t[5]||0)-r,o=d(t[6]||0),t=Math.round(1e3*parseFloat("0."+(t[7]||0))),a.call(e,i,r,o,t)}return e}var n=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(n,i,r){var a,s,l="",u=[];if(i=i||"mediumDate",i=e.DATETIME_FORMATS[i]||i,w(n)&&(n=Yr.test(n)?d(n):t(n)),x(n)&&(n=new Date(n)),!k(n)||!isFinite(n.getTime()))return n;for(;i;)(s=Wr.exec(i))?i=(u=N(u,s,1)).pop():(u.push(i),i=null);var c=n.getTimezoneOffset();return r&&(c=V(r,c),n=q(n,r,!0)),o(u,function(t){a=Br[t],l+=a?a(n,e.DATETIME_FORMATS,c):"''"===t?"'":t.replace(/(^'|'$)/g,"").replace(/''/g,"'")}),l}}function $n(){return function(e,t){return v(t)&&(t=2),L(e,t)}}function bn(){return function(e,t,n){return t=1/0===Math.abs(Number(t))?Number(t):d(t),li(t)?e:(x(e)&&(e=e.toString()),r(e)?(n=0>(n=!n||isNaN(n)?0:d(n))?Math.max(0,e.length+n):n,0<=t?yn(e,n,n+t):0===n?yn(e,t,e.length):yn(e,Math.max(0,n+t),n)):e)}}function yn(e,t,n){return w(e)?e.slice(t,n):ei.call(e,t,n)}function wn(e){function t(t){return t.map(function(t){var n=1,i=h;if(D(t))i=t;else if(w(t)&&("+"!==t.charAt(0)&&"-"!==t.charAt(0)||(n="-"===t.charAt(0)?-1:1,t=t.substring(1)),""!==t&&(i=e(t)).constant)){var r=i();i=function(e){return e[r]}}return{get:i,descending:n}})}function n(e){switch(typeof e){case"number":case"boolean":case"string":return!0;default:return!1}}function o(e,t){var n=0,i=e.type;if(i===(r=t.type)){var r=e.value,o=t.value;"string"===i?(r=r.toLowerCase(),o=o.toLowerCase()):"object"===i&&(b(r)&&(r=e.index),b(o)&&(o=t.index)),r!==o&&(n=rt||37<=t&&40>=t||c(e,this,this.value)}),r.hasEvent("paste")&&t.on("paste cut drop",c)}t.on("change",u),po[a]&&i.$$hasNativeValidators&&a===n.type&&t.on("keydown wheel mousedown",function(e){if(!l){var t=this.validity,n=t.badInput,i=t.typeMismatch;l=o.defer(function(){l=null,t.badInput===n&&t.typeMismatch===i||u(e)})}}),i.$render=function(){var e=i.$isEmpty(i.$viewValue)?"":i.$viewValue;t.val()!==e&&t.val(e)}}function Tn(e,t){return function(n,i){var r,a;if(k(n))return n;if(w(n)){if('"'===n.charAt(0)&&'"'===n.charAt(n.length-1)&&(n=n.substring(1,n.length-1)),no.test(n))return new Date(n);if(e.lastIndex=0,r=e.exec(n))return r.shift(),a=i?{yyyy:i.getFullYear(),MM:i.getMonth()+1,dd:i.getDate(),HH:i.getHours(),mm:i.getMinutes(),ss:i.getSeconds(),sss:i.getMilliseconds()/1e3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},o(r,function(e,n){na.yyyy&&r.setFullYear(a.yyyy),r}return NaN}}function An(e,t,n,i){return function(r,o,a,s,l,u,c,d){function p(e){return e&&!(e.getTime&&e.getTime()!=e.getTime())}function f(e){return $(e)&&!k(e)?h(e)||void 0:e}function h(e,t){var i=s.$options.getOption("timezone");g&&g!==i&&(t=z(t,V(g)));var r=n(e,t);return!isNaN(r)&&i&&(r=q(r,i)),r}Mn(r,o,a,s,e),On(0,o,a,s,l,u);var m,g,b="time"===e||"datetimelocal"===e;if(s.$parsers.push(function(n){return s.$isEmpty(n)?null:t.test(n)?h(n,m):void(s.$$parserName=e)}),s.$formatters.push(function(e){if(e&&!k(e))throw Uo("datefmt",e);if(p(e)){m=e;var t=s.$options.getOption("timezone");t&&(g=t,m=q(m,t,!0));var n=i;return b&&w(s.$options.getOption("timeSecondsFormat"))&&(n=i.replace("ss.sss",s.$options.getOption("timeSecondsFormat")).replace(/:$/,"")),e=c("date")(e,n,t),b&&s.$options.getOption("timeStripZeroSeconds")&&(e=e.replace(/(?::00)?(?:\.000)?$/,"")),e}return g=m=null,""}),$(a.min)||a.ngMin){var y=a.min||d(a.ngMin)(r),x=f(y);s.$validators.min=function(e){return!p(e)||v(x)||n(e)>=x},a.$observe("min",function(e){e!==y&&(x=f(e),y=e,s.$validate())})}if($(a.max)||a.ngMax){var C=a.max||d(a.ngMax)(r),E=f(C);s.$validators.max=function(e){return!p(e)||v(E)||n(e)<=E},a.$observe("max",function(e){e!==C&&(E=f(e),C=e,s.$validate())})}}}function Mn(e,t,n,i,r){(i.$$hasNativeValidators=b(t[0].validity))&&i.$parsers.push(function(e){var n=t.prop("validity")||{};if(!n.badInput&&!n.typeMismatch)return e;i.$$parserName=r})}function _n(e){e.$parsers.push(function(t){return e.$isEmpty(t)?null:oo.test(t)?parseFloat(t):void(e.$$parserName="number")}),e.$formatters.push(function(t){if(!e.$isEmpty(t)){if(!x(t))throw Uo("numfmt",t);t=t.toString()}return t})}function Pn(e){return $(e)&&!x(e)&&(e=parseFloat(e)),li(e)?void 0:e}function In(e){var t=e.toString(),n=t.indexOf(".");return-1===n?-1e&&(e=/e-(\d+)$/.exec(t))?Number(e[1]):0:t.length-n-1}function Rn(e,t,n){var i=(0|(e=Number(e)))!==e,r=(0|t)!==t,o=(0|n)!==n;if(i||r||o){var a=i?In(e):0,s=r?In(t):0,l=o?In(n):0;a=Math.max(a,s,l);e*=a=Math.pow(10,a),t*=a,n*=a,i&&(e=Math.round(e)),r&&(t=Math.round(t)),o&&(n=Math.round(n))}return 0==(e-t)%n}function Fn(e,t,n,i,r){if($(i)){if(!(e=e(i)).constant)throw Uo("constexpr",n,i);return e(t)}return r}function Nn(e,t){function n(e,t){if(!e||!e.length)return[];if(!t||!t.length)return e;var n=[],i=0;e:for(;i(?:<\/\1>|)$/,Ai=/<|&#?\w+;/,Mi=/<([\w:-]+)/,_i=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,Pi={thead:["table"],col:["colgroup","table"],tr:["tbody","table"],td:["tr","tbody","table"]};Pi.tbody=Pi.tfoot=Pi.colgroup=Pi.caption=Pi.thead,Pi.th=Pi.td;var Ii,Ri={option:[1,'"],_default:[0,"",""]};for(Ii in Pi){var Fi=Pi[Ii],Ni=Fi.slice().reverse();Ri[Ii]=[Ni.length,"<"+Ni.join("><")+">",""]}Ri.optgroup=Ri.option;var Ui=e.Node.prototype.contains||function(e){return!!(16&this.compareDocumentPosition(e))},ji=he.prototype={ready:Me,toString:function(){var e=[];return o(this,function(t){e.push(""+t)}),"["+e.join(", ")+"]"},eq:function(e){return Wn(0<=e?this[e]:this[this.length+e])},length:0,push:ni,sort:[].sort,splice:[].splice},Li={};o("multiple selected checked disabled readOnly required open".split(" "),function(e){Li[Jn(e)]=e});var Hi={};o("input select option textarea button form details".split(" "),function(e){Hi[e]=!0});var Vi={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern",ngStep:"step"};o({data:xe,removeData:ye,hasData:function(e){for(var t in ki[e.ng339])return!0;return!1},cleanData:function(e){for(var t=0,n=e.length;t/,Yi=/^[^(]*\(\s*([^)]*)\)/m,Gi=/,/,Xi=/^\s*(_?)(\S+?)\1\s*$/,Ki=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,Zi=i("$injector");je.$$annotate=function(e,t,n){var i;if("function"==typeof e){if(!(i=e.$inject)){if(i=[],e.length){if(t)throw w(n)&&n||(n=e.name||function(e){return(e=Ue(e))?"function("+(e[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}(e)),Zi("strictdi",n);o((t=Ue(e))[1].split(Gi),function(e){e.replace(Xi,function(e,t,n){i.push(n)})})}e.$inject=i}}else C(e)?(ie(e[t=e.length-1],"fn"),i=e.slice(0,t)):ie(e,"fn",!0);return i};var Ji=i("$animate"),Qi=function(){this.$get=f},er=function(){var e=new qi,t=[];this.$get=["$$AnimateRunner","$rootScope",function(n,i){function r(e,t,n){var i=!1;return t&&o(t=w(t)?t.split(" "):C(t)?t:[],function(t){t&&(i=!0,e[t]=n)}),i}function a(){o(t,function(t){var n=e.get(t);if(n){var i=function(e){w(e)&&(e=e.split(" "));var t=ae();return o(e,function(e){e.length&&(t[e]=!0)}),t}(t.attr("class")),r="",a="";o(n,function(e,t){e!==!!i[t]&&(e?r+=(r.length?" ":"")+t:a+=(a.length?" ":"")+t)}),o(t,function(e){r&&Ee(e,r),a&&Ce(e,a)}),e.delete(t)}}),t.length=0}return{enabled:f,on:f,off:f,pin:f,push:function(o,s,l,u){return u&&u(),(l=l||{}).from&&o.css(l.from),l.to&&o.css(l.to),(l.addClass||l.removeClass)&&(s=l.addClass,u=l.removeClass,s=r(l=e.get(o)||{},s,!0),u=r(l,u,!1),(s||u)&&(e.set(o,l),t.push(o),1===t.length&&i.$$postDigest(a))),(o=new n).complete(),o}}}]},tr=["$provide",function(e){var t=this,n=null,i=null;this.$$registeredAnimations=Object.create(null),this.register=function(n,i){if(n&&"."!==n.charAt(0))throw Ji("notcsel",n);var r=n+"-animation";t.$$registeredAnimations[n.substr(1)]=r,e.factory(r,i)},this.customFilter=function(e){return 1===arguments.length&&(i=D(e)?e:null),i},this.classNameFilter=function(e){if(1===arguments.length&&(n=e instanceof RegExp?e:null)&&/[(\s|\/)]ng-animate[(\s|\/)]/.test(n.toString()))throw n=null,Ji("nongcls","ng-animate");return n},this.$get=["$$animateQueue",function(e){function t(e,t,n){if(n){var i;e:{for(i=0;i <= >= && || ! = |".split(" "),function(e){Or[e]=!0});var Tr={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},Ar=function(e){this.options=e};Ar.prototype={constructor:Ar,lex:function(e){for(this.text=e,this.index=0,this.tokens=[];this.index=e&&"string"==typeof e},isWhitespace:function(e){return" "===e||"\r"===e||"\t"===e||"\n"===e||"\v"===e||"Β "===e},isIdentifierStart:function(e){return this.options.isIdentifierStart?this.options.isIdentifierStart(e,this.codePointAt(e)):this.isValidIdentifierStart(e)},isValidIdentifierStart:function(e){return"a"<=e&&"z">=e||"A"<=e&&"Z">=e||"_"===e||"$"===e},isIdentifierContinue:function(e){return this.options.isIdentifierContinue?this.options.isIdentifierContinue(e,this.codePointAt(e)):this.isValidIdentifierContinue(e)},isValidIdentifierContinue:function(e,t){return this.isValidIdentifierStart(e,t)||this.isNumber(e)},codePointAt:function(e){return 1===e.length?e.charCodeAt(0):(e.charCodeAt(0)<<10)+e.charCodeAt(1)-56613888},peekMultichar:function(){var e=this.text.charAt(this.index),t=this.peek();if(!t)return e;var n=e.charCodeAt(0),i=t.charCodeAt(0);return 55296<=n&&56319>=n&&56320<=i&&57343>=i?e+t:e},isExpOperator:function(e){return"-"===e||"+"===e||this.isNumber(e)},throwError:function(e,t,n){throw n=n||this.index,t=$(t)?"s "+t+"-"+this.index+" ["+this.text.substring(t,n)+"]":" "+n,Dr("lexerr",e,t,this.text)},readNumber:function(){for(var e="",t=this.index;this.index","<=",">=");)t={type:Mr.BinaryExpression,operator:e.text,left:t,right:this.additive()};return t},additive:function(){for(var e,t=this.multiplicative();e=this.expect("+","-");)t={type:Mr.BinaryExpression,operator:e.text,left:t,right:this.multiplicative()};return t},multiplicative:function(){for(var e,t=this.unary();e=this.expect("*","/","%");)t={type:Mr.BinaryExpression,operator:e.text,left:t,right:this.unary()};return t},unary:function(){var e;return(e=this.expect("+","-","!"))?{type:Mr.UnaryExpression,operator:e.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var e,t;for(this.expect("(")?(e=this.filterChain(),this.consume(")")):this.expect("[")?e=this.arrayDeclaration():this.expect("{")?e=this.object():this.selfReferential.hasOwnProperty(this.peek().text)?e=I(this.selfReferential[this.consume().text]):this.options.literals.hasOwnProperty(this.peek().text)?e={type:Mr.Literal,value:this.options.literals[this.consume().text]}:this.peek().identifier?e=this.identifier():this.peek().constant?e=this.constant():this.throwError("not a primary expression",this.peek());t=this.expect("(","[",".");)"("===t.text?(e={type:Mr.CallExpression,callee:e,arguments:this.parseArguments()},this.consume(")")):"["===t.text?(e={type:Mr.MemberExpression,object:e,property:this.expression(),computed:!0},this.consume("]")):"."===t.text?e={type:Mr.MemberExpression,object:e,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return e},filter:function(e){e=[e];for(var t={type:Mr.CallExpression,callee:this.identifier(),arguments:e,filter:!0};this.expect(":");)e.push(this.expression());return t},parseArguments:function(){var e=[];if(")"!==this.peekToken().text)do{e.push(this.filterChain())}while(this.expect(","));return e},identifier:function(){var e=this.consume();return e.identifier||this.throwError("is not a valid identifier",e),{type:Mr.Identifier,name:e.text}},constant:function(){return{type:Mr.Literal,value:this.consume().value}},arrayDeclaration:function(){var e=[];if("]"!==this.peekToken().text)do{if(this.peek("]"))break;e.push(this.expression())}while(this.expect(","));return this.consume("]"),{type:Mr.ArrayExpression,elements:e}},object:function(){var e,t=[];if("}"!==this.peekToken().text)do{if(this.peek("}"))break;e={type:Mr.Property,kind:"init"},this.peek().constant?(e.key=this.constant(),e.computed=!1,this.consume(":"),e.value=this.expression()):this.peek().identifier?(e.key=this.identifier(),e.computed=!1,this.peek(":")?(this.consume(":"),e.value=this.expression()):e.value=e.key):this.peek("[")?(this.consume("["),e.key=this.expression(),this.consume("]"),e.computed=!0,this.consume(":"),e.value=this.expression()):this.throwError("invalid key",this.peek()),t.push(e)}while(this.expect(","));return this.consume("}"),{type:Mr.ObjectExpression,properties:t}},throwError:function(e,t){throw Dr("syntax",t.text,e,t.index+1,this.text,this.text.substring(t.index))},consume:function(e){if(0===this.tokens.length)throw Dr("ueoe",this.text);var t=this.expect(e);return t||this.throwError("is unexpected, expecting ["+e+"]",this.peek()),t},peekToken:function(){if(0===this.tokens.length)throw Dr("ueoe",this.text);return this.tokens[0]},peek:function(e,t,n,i){return this.peekAhead(0,e,t,n,i)},peekAhead:function(e,t,n,i,r){if(this.tokens.length>e){var o=(e=this.tokens[e]).text;if(o===t||o===n||o===i||o===r||!(t||n||i||r))return e}return!1},expect:function(e,t,n,i){return!!(e=this.peek(e,t,n,i))&&(this.tokens.shift(),e)},selfReferential:{this:{type:Mr.ThisExpression},$locals:{type:Mr.LocalsExpression}}};var _r=2;Pt.prototype={compile:function(e){var t=this;this.state={nextId:0,filters:{},fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]},Tt(e,t.$filter);var n,i="";return this.stage="assign",(n=_t(e))&&(this.state.computing="assign",i=this.nextId(),this.recurse(n,i),this.return_(i),i="fn.assign="+this.generateFunction("assign","s,v,l")),n=At(e.body),t.stage="inputs",o(n,function(e,n){var i="fn"+n;t.state[i]={vars:[],body:[],own:{}},t.state.computing=i;var r=t.nextId();t.recurse(e,r),t.return_(r),t.state.inputs.push({name:i,isPure:e.isPure}),e.watchId=n}),this.state.computing="fn",this.stage="main",this.recurse(e),e='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+i+this.watchFns()+"return fn;",e=new Function("$filter","getStringValue","ifDefined","plus",e)(this.$filter,Dt,St,Ot),this.state=this.stage=void 0,e},USE:"use",STRICT:"strict",watchFns:function(){var e=[],t=this.state.inputs,n=this;return o(t,function(t){e.push("var "+t.name+"="+n.generateFunction(t.name,"s")),t.isPure&&e.push(t.name,".isPure="+JSON.stringify(t.isPure)+";")}),t.length&&e.push("fn.inputs=["+t.map(function(e){return e.name}).join(",")+"];"),e.join("")},generateFunction:function(e,t){return"function("+t+"){"+this.varsPrefix(e)+this.body(e)+"};"},filterPrefix:function(){var e=[],t=this;return o(this.state.filters,function(n,i){e.push(n+"=$filter("+t.escape(i)+")")}),e.length?"var "+e.join(",")+";":""},varsPrefix:function(e){return this.state[e].vars.length?"var "+this.state[e].vars.join(",")+";":""},body:function(e){return this.state[e].body.join("")},recurse:function(e,t,n,i,r,a){var s,l,u,c,d,p=this;if(i=i||f,!a&&$(e.watchId))t=t||this.nextId(),this.if_("i",this.lazyAssign(t,this.computedMember("i",e.watchId)),this.lazyRecurse(e,t,n,i,r,!0));else switch(e.type){case Mr.Program:o(e.body,function(t,n){p.recurse(t.expression,void 0,void 0,function(e){l=e}),n!==e.body.length-1?p.current().body.push(l,";"):p.return_(l)});break;case Mr.Literal:c=this.escape(e.value),this.assign(t,c),i(t||c);break;case Mr.UnaryExpression:this.recurse(e.argument,void 0,void 0,function(e){l=e}),c=e.operator+"("+this.ifDefined(l,0)+")",this.assign(t,c),i(c);break;case Mr.BinaryExpression:this.recurse(e.left,void 0,void 0,function(e){s=e}),this.recurse(e.right,void 0,void 0,function(e){l=e}),c="+"===e.operator?this.plus(s,l):"-"===e.operator?this.ifDefined(s,0)+e.operator+this.ifDefined(l,0):"("+s+")"+e.operator+"("+l+")",this.assign(t,c),i(c);break;case Mr.LogicalExpression:t=t||this.nextId(),p.recurse(e.left,t),p.if_("&&"===e.operator?t:p.not(t),p.lazyRecurse(e.right,t)),i(t);break;case Mr.ConditionalExpression:t=t||this.nextId(),p.recurse(e.test,t),p.if_(t,p.lazyRecurse(e.alternate,t),p.lazyRecurse(e.consequent,t)),i(t);break;case Mr.Identifier:t=t||this.nextId(),n&&(n.context="inputs"===p.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",e.name)+"?l:s"),n.computed=!1,n.name=e.name),p.if_("inputs"===p.stage||p.not(p.getHasOwnProperty("l",e.name)),function(){p.if_("inputs"===p.stage||"s",function(){r&&1!==r&&p.if_(p.isNull(p.nonComputedMember("s",e.name)),p.lazyAssign(p.nonComputedMember("s",e.name),"{}")),p.assign(t,p.nonComputedMember("s",e.name))})},t&&p.lazyAssign(t,p.nonComputedMember("l",e.name))),i(t);break;case Mr.MemberExpression:s=n&&(n.context=this.nextId())||this.nextId(),t=t||this.nextId(),p.recurse(e.object,s,void 0,function(){p.if_(p.notNull(s),function(){e.computed?(l=p.nextId(),p.recurse(e.property,l),p.getStringValue(l),r&&1!==r&&p.if_(p.not(p.computedMember(s,l)),p.lazyAssign(p.computedMember(s,l),"{}")),c=p.computedMember(s,l),p.assign(t,c),n&&(n.computed=!0,n.name=l)):(r&&1!==r&&p.if_(p.isNull(p.nonComputedMember(s,e.property.name)),p.lazyAssign(p.nonComputedMember(s,e.property.name),"{}")),c=p.nonComputedMember(s,e.property.name),p.assign(t,c),n&&(n.computed=!1,n.name=e.property.name))},function(){p.assign(t,"undefined")}),i(t)},!!r);break;case Mr.CallExpression:t=t||this.nextId(),e.filter?(l=p.filter(e.callee.name),u=[],o(e.arguments,function(e){var t=p.nextId();p.recurse(e,t),u.push(t)}),c=l+"("+u.join(",")+")",p.assign(t,c),i(t)):(l=p.nextId(),s={},u=[],p.recurse(e.callee,l,s,function(){p.if_(p.notNull(l),function(){o(e.arguments,function(t){p.recurse(t,e.constant?void 0:p.nextId(),void 0,function(e){u.push(e)})}),c=s.name?p.member(s.context,s.name,s.computed)+"("+u.join(",")+")":l+"("+u.join(",")+")",p.assign(t,c)},function(){p.assign(t,"undefined")}),i(t)}));break;case Mr.AssignmentExpression:l=this.nextId(),s={},this.recurse(e.left,void 0,s,function(){p.if_(p.notNull(s.context),function(){p.recurse(e.right,l),c=p.member(s.context,s.name,s.computed)+e.operator+l,p.assign(t,c),i(t||c)})},1);break;case Mr.ArrayExpression:u=[],o(e.elements,function(t){p.recurse(t,e.constant?void 0:p.nextId(),void 0,function(e){u.push(e)})}),c="["+u.join(",")+"]",this.assign(t,c),i(t||c);break;case Mr.ObjectExpression:u=[],d=!1,o(e.properties,function(e){e.computed&&(d=!0)}),d?(t=t||this.nextId(),this.assign(t,"{}"),o(e.properties,function(e){e.computed?(s=p.nextId(),p.recurse(e.key,s)):s=e.key.type===Mr.Identifier?e.key.name:""+e.key.value,l=p.nextId(),p.recurse(e.value,l),p.assign(p.member(t,s,e.computed),l)})):(o(e.properties,function(t){p.recurse(t.value,e.constant?void 0:p.nextId(),void 0,function(e){u.push(p.escape(t.key.type===Mr.Identifier?t.key.name:""+t.key.value)+":"+e)})}),c="{"+u.join(",")+"}",this.assign(t,c)),i(t||c);break;case Mr.ThisExpression:this.assign(t,"s"),i(t||"s");break;case Mr.LocalsExpression:this.assign(t,"l"),i(t||"l");break;case Mr.NGValueParameter:this.assign(t,"v"),i(t||"v")}},getHasOwnProperty:function(e,t){var n=e+"."+t,i=this.current().own;return i.hasOwnProperty(n)||(i[n]=this.nextId(!1,e+"&&("+this.escape(t)+" in "+e+")")),i[n]},assign:function(e,t){if(e)return this.current().body.push(e,"=",t,";"),e},filter:function(e){return this.state.filters.hasOwnProperty(e)||(this.state.filters[e]=this.nextId(!0)),this.state.filters[e]},ifDefined:function(e,t){return"ifDefined("+e+","+this.escape(t)+")"},plus:function(e,t){return"plus("+e+","+t+")"},return_:function(e){this.current().body.push("return ",e,";")},if_:function(e,t,n){if(!0===e)t();else{var i=this.current().body;i.push("if(",e,"){"),t(),i.push("}"),n&&(i.push("else{"),n(),i.push("}"))}},not:function(e){return"!("+e+")"},isNull:function(e){return e+"==null"},notNull:function(e){return e+"!=null"},nonComputedMember:function(e,t){return/^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(t)?e+"."+t:e+'["'+t.replace(/[^$_a-zA-Z0-9]/g,this.stringEscapeFn)+'"]'},computedMember:function(e,t){return e+"["+t+"]"},member:function(e,t,n){return n?this.computedMember(e,t):this.nonComputedMember(e,t)},getStringValue:function(e){this.assign(e,"getStringValue("+e+")")},lazyRecurse:function(e,t,n,i,r,o){var a=this;return function(){a.recurse(e,t,n,i,r,o)}},lazyAssign:function(e,t){var n=this;return function(){n.assign(e,t)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)},escape:function(e){if(w(e))return"'"+e.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(x(e))return e.toString();if(!0===e)return"true";if(!1===e)return"false";if(null===e)return"null";if(void 0===e)return"undefined";throw Dr("esc")},nextId:function(e,t){var n="v"+this.state.nextId++;return e||this.current().vars.push(n+(t?"="+t:"")),n},current:function(){return this.state[this.state.computing]}},It.prototype={compile:function(e){var t,n,i,r=this;Tt(e,r.$filter),(t=_t(e))&&(n=this.recurse(t)),(t=At(e.body))&&(i=[],o(t,function(e,t){var n=r.recurse(e);n.isPure=e.isPure,e.input=n,i.push(n),e.watchId=t}));var a=[];return o(e.body,function(e){a.push(r.recurse(e.expression))}),e=0===e.body.length?f:1===e.body.length?a[0]:function(e,t){var n;return o(a,function(i){n=i(e,t)}),n},n&&(e.assign=function(e,t,i){return n(e,i,t)}),i&&(e.inputs=i),e},recurse:function(e,t,n){var i,r,a,s=this;if(e.input)return this.inputs(e.input,e.watchId);switch(e.type){case Mr.Literal:return this.value(e.value,t);case Mr.UnaryExpression:return r=this.recurse(e.argument),this["unary"+e.operator](r,t);case Mr.BinaryExpression:case Mr.LogicalExpression:return i=this.recurse(e.left),r=this.recurse(e.right),this["binary"+e.operator](i,r,t);case Mr.ConditionalExpression:return this["ternary?:"](this.recurse(e.test),this.recurse(e.alternate),this.recurse(e.consequent),t);case Mr.Identifier:return s.identifier(e.name,t,n);case Mr.MemberExpression:return i=this.recurse(e.object,!1,!!n),e.computed||(r=e.property.name),e.computed&&(r=this.recurse(e.property)),e.computed?this.computedMember(i,r,t,n):this.nonComputedMember(i,r,t,n);case Mr.CallExpression:return a=[],o(e.arguments,function(e){a.push(s.recurse(e))}),e.filter&&(r=this.$filter(e.callee.name)),e.filter||(r=this.recurse(e.callee,!0)),e.filter?function(e,n,i,o){for(var s=[],l=0;l":function(e,t,n){return function(i,r,o,a){return i=e(i,r,o,a)>t(i,r,o,a),n?{value:i}:i}},"binary<=":function(e,t,n){return function(i,r,o,a){return i=e(i,r,o,a)<=t(i,r,o,a),n?{value:i}:i}},"binary>=":function(e,t,n){return function(i,r,o,a){return i=e(i,r,o,a)>=t(i,r,o,a),n?{value:i}:i}},"binary&&":function(e,t,n){return function(i,r,o,a){return i=e(i,r,o,a)&&t(i,r,o,a),n?{value:i}:i}},"binary||":function(e,t,n){return function(i,r,o,a){return i=e(i,r,o,a)||t(i,r,o,a),n?{value:i}:i}},"ternary?:":function(e,t,n,i){return function(r,o,a,s){return r=e(r,o,a,s)?t(r,o,a,s):n(r,o,a,s),i?{value:r}:r}},value:function(e,t){return function(){return t?{context:void 0,name:void 0,value:e}:e}},identifier:function(e,t,n){return function(i,r,o,a){return i=r&&e in r?r:i,n&&1!==n&&i&&null==i[e]&&(i[e]={}),r=i?i[e]:void 0,t?{context:i,name:e,value:r}:r}},computedMember:function(e,t,n,i){return function(r,o,a,s){var l,u,c=e(r,o,a,s);return null!=c&&(l=t(r,o,a,s),l+="",i&&1!==i&&c&&!c[l]&&(c[l]={}),u=c[l]),n?{context:c,name:l,value:u}:u}},nonComputedMember:function(e,t,n,i){return function(r,o,a,s){return r=e(r,o,a,s),i&&1!==i&&r&&null==r[t]&&(r[t]={}),o=null!=r?r[t]:void 0,n?{context:r,name:t,value:o}:o}},inputs:function(e,t){return function(n,i,r,o){return o?o[t]:e(n,i,r)}}},Rt.prototype={constructor:Rt,parse:function(e){e=this.getAst(e);var t=this.astCompiler.compile(e.ast),n=e.ast;return t.literal=0===n.body.length||1===n.body.length&&(n.body[0].expression.type===Mr.Literal||n.body[0].expression.type===Mr.ArrayExpression||n.body[0].expression.type===Mr.ObjectExpression),t.constant=e.ast.constant,t.oneTime=e.oneTime,t},getAst:function(e){var t=!1;return":"===(e=e.trim()).charAt(0)&&":"===e.charAt(1)&&(t=!0,e=e.substring(2)),{ast:this.ast.ast(e),oneTime:t}}};var Pr,Ir=i("$sce"),Rr={HTML:"html",CSS:"css",MEDIA_URL:"mediaUrl",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},Fr=/_([a-z])/g,Nr=i("$templateRequest"),Ur=i("$timeout"),jr=e.document.createElement("a"),Lr=Jt(e.location.href);jr.href="http://[::1]";var Hr="[::1]"===jr.hostname;tn.$inject=["$document"],rn.$inject=["$provide"];var Vr=22,zr=".",qr="0";ln.$inject=["$locale"],un.$inject=["$locale"];var Br={yyyy:pn("FullYear",4,0,!1,!0),yy:pn("FullYear",2,0,!0,!0),y:pn("FullYear",1,0,!1,!0),MMMM:fn("Month"),MMM:fn("Month",!0),MM:pn("Month",2,1),M:pn("Month",1,1),LLLL:fn("Month",!1,!0),dd:pn("Date",2),d:pn("Date",1),HH:pn("Hours",2),H:pn("Hours",1),hh:pn("Hours",2,-12),h:pn("Hours",1,-12),mm:pn("Minutes",2),m:pn("Minutes",1),ss:pn("Seconds",2),s:pn("Seconds",1),sss:pn("Milliseconds",3),EEEE:fn("Day"),EEE:fn("Day",!0),a:function(e,t){return 12>e.getHours()?t.AMPMS[0]:t.AMPMS[1]},Z:function(e,t,n){return(0<=(e=-1*n)?"+":"")+(dn(Math[0=e.getFullYear()?t.ERANAMES[0]:t.ERANAMES[1]}},Wr=/((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))([\s\S]*)/,Yr=/^-?\d+$/;vn.$inject=["$locale"];var Gr=m(Jn),Xr=m(Qn);wn.$inject=["$parse"];var Kr=m({restrict:"E",compile:function(e,t){if(!t.href&&!t.xlinkHref)return function(e,t){if("a"===t[0].nodeName.toLowerCase()){var n="[object SVGAnimatedString]"===ii.call(t.prop("href"))?"xlink:href":"href";t.on("click",function(e){t.attr(n)||e.preventDefault()})}}}}),Zr={};o(Li,function(e,t){function n(e,n,r){e.$watch(r[i],function(e){r.$set(t,!!e)})}if("multiple"!==e){var i=Ge("ng-"+t),r=n;"checked"===e&&(r=function(e,t,r){r.ngModel!==r[i]&&n(e,0,r)}),Zr[i]=function(){return{restrict:"A",priority:100,link:r}}}}),o(Vi,function(e,t){Zr[t]=function(){return{priority:100,link:function(e,n,i){"ngPattern"===t&&"/"===i.ngPattern.charAt(0)&&(n=i.ngPattern.match(Kn))?i.$set("ngPattern",new RegExp(n[1],n[2])):e.$watch(i[t],function(e){i.$set(t,e)})}}}}),o(["src","srcset","href"],function(e){var t=Ge("ng-"+e);Zr[t]=["$sce",function(n){return{priority:99,link:function(i,r,o){var a=e,s=e;"href"===e&&"[object SVGAnimatedString]"===ii.call(r.prop("href"))&&(s="xlinkHref",o.$attr[s]="xlink:href",a=null),o.$set(t,n.getTrustedMediaUrl(o[t])),o.$observe(t,function(t){t?(o.$set(s,t),Bn&&a&&r.prop(a,o[s])):"href"===e&&o.$set(s,null)})}}}]});var Jr={$addControl:f,$getControls:m([]),$$renameControl:function(e,t){e.$name=t},$removeControl:f,$setValidity:f,$setDirty:f,$setPristine:f,$setSubmitted:f,$$setSubmitted:f};kn.$inject=["$element","$attrs","$scope","$animate","$interpolate"],kn.prototype={$rollbackViewValue:function(){o(this.$$controls,function(e){e.$rollbackViewValue()})},$commitViewValue:function(){o(this.$$controls,function(e){e.$commitViewValue()})},$addControl:function(e){re(e.$name,"input"),this.$$controls.push(e),e.$name&&(this[e.$name]=e),e.$$parentForm=this},$getControls:function(){return le(this.$$controls)},$$renameControl:function(e,t){var n=e.$name;this[n]===e&&delete this[n],this[t]=e,e.$name=t},$removeControl:function(e){e.$name&&this[e.$name]===e&&delete this[e.$name],o(this.$pending,function(t,n){this.$setValidity(n,null,e)},this),o(this.$error,function(t,n){this.$setValidity(n,null,e)},this),o(this.$$success,function(t,n){this.$setValidity(n,null,e)},this),P(this.$$controls,e),e.$$parentForm=Jr},$setDirty:function(){this.$$animate.removeClass(this.$$element,Fo),this.$$animate.addClass(this.$$element,No),this.$dirty=!0,this.$pristine=!1,this.$$parentForm.$setDirty()},$setPristine:function(){this.$$animate.setClass(this.$$element,Fo,No+" ng-submitted"),this.$dirty=!1,this.$pristine=!0,this.$submitted=!1,o(this.$$controls,function(e){e.$setPristine()})},$setUntouched:function(){o(this.$$controls,function(e){e.$setUntouched()})},$setSubmitted:function(){for(var e=this;e.$$parentForm&&e.$$parentForm!==Jr;)e=e.$$parentForm;e.$$setSubmitted()},$$setSubmitted:function(){this.$$animate.addClass(this.$$element,"ng-submitted"),this.$submitted=!0,o(this.$$controls,function(e){e.$$setSubmitted&&e.$$setSubmitted()})}},En({clazz:kn,set:function(e,t,n){var i=e[t];i?-1===i.indexOf(n)&&i.push(n):e[t]=[n]},unset:function(e,t,n){var i=e[t];i&&(P(i,n),0===i.length&&delete e[t])}});var Qr=function(e){return["$timeout","$parse",function(t,n){function i(e){return""===e?n('this[""]').assign:n(e).assign||f}return{name:"form",restrict:e?"EAC":"E",require:["form","^^?form"],controller:kn,compile:function(n,r){n.addClass(Fo).addClass(Io);var o=r.name?"name":!(!e||!r.ngForm)&&"ngForm";return{pre:function(e,n,r,a){var s=a[0];if(!("action"in r)){var l=function(t){e.$apply(function(){s.$commitViewValue(),s.$setSubmitted()}),t.preventDefault()};n[0].addEventListener("submit",l),n.on("$destroy",function(){t(function(){n[0].removeEventListener("submit",l)},0,!1)})}(a[1]||s.$$parentForm).$addControl(s);var c=o?i(s.$name):f;o&&(c(e,s),r.$observe(o,function(t){s.$name!==t&&(c(e,void 0),s.$$parentForm.$$renameControl(s,t),(c=i(s.$name))(e,s))})),n.on("$destroy",function(){s.$$parentForm.$removeControl(s),c(e,void 0),u(s,Jr)})}}}}}]},eo=Qr(),to=Qr(!0),no=/^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/,io=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,ro=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,oo=/^\s*(-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,ao=/^(\d{4,})-(\d{2})-(\d{2})$/,so=/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,lo=/^(\d{4,})-W(\d\d)$/,uo=/^(\d{4,})-(\d\d)$/,co=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,po=ae();o(["date","datetime-local","month","time","week"],function(e){po[e]=!0});var fo={text:function(e,t,n,i,r,o){On(0,t,n,i,r,o),Sn(i)},date:An("date",ao,Tn(ao,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":An("datetimelocal",so,Tn(so,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:An("time",co,Tn(co,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:An("week",lo,function(e,t){if(k(e))return e;if(w(e)){lo.lastIndex=0;var n=lo.exec(e);if(n){var i=+n[1],r=+n[2],o=n=0,a=0,s=0,l=hn(i);r=7*(r-1);return t&&(n=t.getHours(),o=t.getMinutes(),a=t.getSeconds(),s=t.getMilliseconds()),new Date(i,0,l.getDate()+r,n,o,a,s)}}return NaN},"yyyy-Www"),month:An("month",uo,Tn(uo,["yyyy","MM"]),"yyyy-MM"),number:function(e,t,n,i,r,o,a,s){var l;if(Mn(0,t,0,i,"number"),_n(i),On(0,t,n,i,r,o),$(n.min)||n.ngMin){var u=n.min||s(n.ngMin)(e);l=Pn(u),i.$validators.min=function(e,t){return i.$isEmpty(t)||v(l)||t>=l},n.$observe("min",function(e){e!==u&&(l=Pn(e),u=e,i.$validate())})}if($(n.max)||n.ngMax){var c=n.max||s(n.ngMax)(e),d=Pn(c);i.$validators.max=function(e,t){return i.$isEmpty(t)||v(d)||t<=d},n.$observe("max",function(e){e!==c&&(d=Pn(e),c=e,i.$validate())})}if($(n.step)||n.ngStep){var p=n.step||s(n.ngStep)(e),f=Pn(p);i.$validators.step=function(e,t){return i.$isEmpty(t)||v(f)||Rn(t,l||0,f)},n.$observe("step",function(e){e!==p&&(f=Pn(e),p=e,i.$validate())})}},url:function(e,t,n,i,r,o){On(0,t,n,i,r,o),Sn(i),i.$validators.url=function(e,t){var n=e||t;return i.$isEmpty(n)||io.test(n)}},email:function(e,t,n,i,r,o){On(0,t,n,i,r,o),Sn(i),i.$validators.email=function(e,t){var n=e||t;return i.$isEmpty(n)||ro.test(n)}},radio:function(e,t,n,i){var r=!n.ngTrim||"false"!==pi(n.ngTrim);v(n.name)&&t.attr("name",++si),t.on("change",function(e){var o;t[0].checked&&(o=n.value,r&&(o=pi(o)),i.$setViewValue(o,e&&e.type))}),i.$render=function(){var e=n.value;r&&(e=pi(e)),t[0].checked=e===i.$viewValue},n.$observe("value",i.$render)},range:function(e,t,n,i,r,o){function a(e,i){t.attr(e,n[e]);var r=n[e];n.$observe(e,function(e){e!==r&&(r=e,i(e))})}Mn(0,t,0,i,"range"),_n(i),On(0,t,n,i,r,o);var s=i.$$hasNativeValidators&&"range"===t[0].type,l=s?0:void 0,u=s?100:void 0,c=s?1:void 0,d=t[0].validity;e=$(n.min),r=$(n.max),o=$(n.step);var p=i.$render;i.$render=s&&$(d.rangeUnderflow)&&$(d.rangeOverflow)?function(){p(),i.$setViewValue(t.val())}:p,e&&(l=Pn(n.min),i.$validators.min=s?function(){return!0}:function(e,t){return i.$isEmpty(t)||v(l)||t>=l},a("min",function(e){l=Pn(e),li(i.$modelValue)||(s?(e=t.val(),l>e&&(e=l,t.val(e)),i.$setViewValue(e)):i.$validate())})),r&&(u=Pn(n.max),i.$validators.max=s?function(){return!0}:function(e,t){return i.$isEmpty(t)||v(u)||t<=u},a("max",function(e){u=Pn(e),li(i.$modelValue)||(s?(e=t.val(),ua||r.$isEmpty(t)||t.length<=a}}}}}],fa=["$parse",function(e){return{restrict:"A",require:"?ngModel",link:function(t,n,i,r){if(r){var o=i.minlength||e(i.ngMinlength)(t),a=qn(o)||-1;i.$observe("minlength",function(e){o!==e&&(a=qn(e)||-1,o=e,r.$validate())}),r.$validators.minlength=function(e,t){return r.$isEmpty(t)||t.length>=a}}}}}];e.angular.bootstrap?e.console&&console.log("WARNING: Tried to load AngularJS more than once."):(function(){var t;if(!yi){var n=mi();(Yn=v(n)?e.jQuery:n?e[n]:void 0)&&Yn.fn.on?(Wn=Yn,u(Yn.fn,{scope:ji.scope,isolateScope:ji.isolateScope,controller:ji.controller,injector:ji.injector,inheritedData:ji.inheritedData})):Wn=he,t=Wn.cleanData,Wn.cleanData=function(e){for(var n,i,r=0;null!=(i=e[r]);r++)(n=(Wn._data(i)||{}).events)&&n.$destroy&&Wn(i).triggerHandler("$destroy");t(e)},ai.element=Wn,yi=!0}}(),function(n){u(n,{errorHandlingConfig:t,bootstrap:Z,copy:I,extend:u,merge:c,equals:F,element:Wn,forEach:o,injector:je,noop:f,bind:U,toJson:L,fromJson:H,identity:h,isUndefined:v,isDefined:$,isString:w,isFunction:D,isObject:b,isNumber:x,isElement:M,isArray:C,version:xi,isDate:k,callbacks:{$$counter:0},getTestability:Q,reloadWithDebugInfo:J,UNSAFE_restoreLegacyJqLiteXHTMLReplacement:te,$$minErr:i,$$csp:hi,$$encodeUriSegment:G,$$encodeUriQuery:X,$$lowercase:Jn,$$stringify:se,$$uppercase:Qn}),(Gn=function(e){function t(e,t,n){return e[t]||(e[t]=n())}var n=i("$injector"),r=i("ng");return(e=t(e,"angular",Object)).$$minErr=e.$$minErr||i,t(e,"module",function(){var e={};return function(i,o,a){var s={};if("hasOwnProperty"===i)throw r("badname","module");return o&&e.hasOwnProperty(i)&&(e[i]=null),t(e,i,function(){function e(e,t,n,i){return i||(i=l),function(){return i[n||"push"]([e,t,arguments]),p}}function t(e,t,n){return n||(n=l),function(r,o){return o&&D(o)&&(o.$$moduleName=i),n.push([e,t,arguments]),p}}if(!o)throw n("nomod",i);var l=[],u=[],c=[],d=e("$injector","invoke","push",u),p={_invokeQueue:l,_configBlocks:u,_runBlocks:c,info:function(e){if($(e)){if(!b(e))throw r("aobj","value");return s=e,this}return s},requires:o,name:i,provider:t("$provide","provider"),factory:t("$provide","factory"),service:t("$provide","service"),value:e("$provide","value"),constant:e("$provide","constant","unshift"),decorator:t("$provide","decorator",u),animation:t("$animateProvider","register"),filter:t("$filterProvider","register"),controller:t("$controllerProvider","register"),directive:t("$compileProvider","directive"),component:t("$compileProvider","component"),config:d,run:function(e){return c.push(e),this}};return a&&d(a),p})}})}(e))("ng",["ngLocale"],["$provide",function(e){e.provider({$$sanitizeUri:zt}),e.provider("$compile",We).directive({a:Kr,input:ho,textarea:ho,form:eo,script:oa,select:la,option:ua,ngBind:$o,ngBindHtml:yo,ngBindTemplate:bo,ngClass:xo,ngClassEven:Co,ngClassOdd:ko,ngCloak:Eo,ngController:Do,ngForm:to,ngHide:Jo,ngIf:To,ngInclude:Ao,ngInit:_o,ngNonBindable:zo,ngPluralize:Yo,ngRef:Xo,ngRepeat:Ko,ngShow:Zo,ngStyle:Qo,ngSwitch:ea,ngSwitchWhen:ta,ngSwitchDefault:na,ngOptions:Wo,ngTransclude:ra,ngModel:Lo,ngList:Po,ngChange:wo,pattern:da,ngPattern:da,required:ca,ngRequired:ca,minlength:fa,ngMinlength:fa,maxlength:pa,ngMaxlength:pa,ngValue:vo,ngModelOptions:Vo}).directive({ngInclude:Mo,input:mo}).directive(Zr).directive(So),e.provider({$anchorScroll:Le,$animate:tr,$animateCss:rr,$$animateJs:Qi,$$animateQueue:er,$$AnimateRunner:ir,$$animateAsyncRun:nr,$browser:ze,$cacheFactory:qe,$controller:Ze,$document:Je,$$isDocumentHidden:Qe,$exceptionHandler:et,$filter:rn,$$forceReflow:dr,$interpolate:dt,$interval:pt,$$intervalFactory:ft,$http:lt,$httpParamSerializer:nt,$httpParamSerializerJQLike:it,$httpBackend:ct,$xhrFactory:ut,$jsonpCallbacks:yr,$location:Ct,$log:Et,$parse:Nt,$rootScope:Vt,$q:Ut,$$q:jt,$sce:Wt,$sceDelegate:Bt,$sniffer:Yt,$$taskTrackerFactory:Gt,$templateCache:Be,$templateRequest:Xt,$$testability:Kt,$timeout:Zt,$window:en,$$rAF:Ht,$$jqLite:Re,$$Map:Bi,$$cookieReader:nn})}]).info({angularVersion:"1.8.3"})}(ai),ai.module("ngLocale",[],["$provide",function(e){e.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a",short:"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-Β€",negSuf:"",posPre:"Β€",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(e,t){var n=0|e,i=t;return void 0===i&&(i=Math.min(function(e){var t=(e+="").indexOf(".");return-1==t?0:e.length-t-1}(e),3)),Math.pow(10,i),1==n&&0==i?"one":"other"}})}]),Wn(function(){K(e.document,Z)}))}(window),!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend(window.angular.element("'),angular.$$uibCarouselCss=!0}),angular.module("ui.bootstrap.datepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerCss&&angular.element(document).find("head").prepend(''),angular.$$uibDatepickerCss=!0}),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend(''),angular.$$uibPositionCss=!0}),angular.module("ui.bootstrap.datepickerPopup").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerpopupCss&&angular.element(document).find("head").prepend(''),angular.$$uibDatepickerpopupCss=!0}),angular.module("ui.bootstrap.tooltip").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTooltipCss&&angular.element(document).find("head").prepend(''),angular.$$uibTooltipCss=!0}),angular.module("ui.bootstrap.timepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTimepickerCss&&angular.element(document).find("head").prepend(''),angular.$$uibTimepickerCss=!0}),angular.module("ui.bootstrap.typeahead").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTypeaheadCss&&angular.element(document).find("head").prepend(''),angular.$$uibTypeaheadCss=!0}),function(e,t){var n=t.isDefined,i=t.isUndefined,r=t.isNumber,o=t.isObject,a=t.isArray,s=t.isString,l=t.extend,u=t.toJson;t.module("LocalStorageModule",[]).provider("localStorageService",function(){this.prefix="ls",this.storageType="localStorage",this.cookie={expiry:30,path:"/",secure:!1},this.defaultToCookie=!0,this.notify={setItem:!0,removeItem:!1},this.setPrefix=function(e){return this.prefix=e,this},this.setStorageType=function(e){return this.storageType=e,this},this.setDefaultToCookie=function(e){return this.defaultToCookie=!!e,this},this.setStorageCookie=function(e,t,n){return this.cookie.expiry=e,this.cookie.path=t,this.cookie.secure=n,this},this.setStorageCookieDomain=function(e){return this.cookie.domain=e,this},this.setNotify=function(e,t){return this.notify={setItem:e,removeItem:t},this},this.$get=["$rootScope","$window","$document","$parse","$timeout",function(e,t,c,d,p){function f(n){if(n||(n=t.event),$.setItem&&s(n.key)&&x(n.key)){var i=w(n.key);p(function(){e.$broadcast("LocalStorageModule.notification.changed",{key:i,newvalue:n.newValue,storageType:m.storageType})})}}var h,m=this,g=m.prefix,v=m.cookie,$=m.notify,b=m.storageType;c?c[0]&&(c=c[0]):c=document,"."!==g.substr(-1)&&(g=g?g+".":"");var y=function(e){return g+e},w=function(e){return e.replace(new RegExp("^"+g,"g"),"")},x=function(e){return 0===e.indexOf(g)},k=function(){try{var n=b in t&&null!==t[b],i=y("__"+Math.round(1e7*Math.random()));return n&&((h=t[b]).setItem(i,""),h.removeItem(i)),n}catch(t){return m.defaultToCookie&&(b="cookie"),e.$broadcast("LocalStorageModule.notification.error",t.message),!1}},C=k(),E=function(t,n,r){var o=P();try{if(I(r),n=i(n)?null:u(n),!C&&m.defaultToCookie||"cookie"===m.storageType)return C||e.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),$.setItem&&e.$broadcast("LocalStorageModule.notification.setitem",{key:t,newvalue:n,storageType:"cookie"}),T(t,n);try{h&&h.setItem(y(t),n),$.setItem&&e.$broadcast("LocalStorageModule.notification.setitem",{key:t,newvalue:n,storageType:m.storageType})}catch(i){return e.$broadcast("LocalStorageModule.notification.error",i.message),T(t,n)}return!0}finally{I(o)}},D=function(t,n){var i=P();try{if(I(n),!C&&m.defaultToCookie||"cookie"===m.storageType)return C||e.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),A(t);var r=h?h.getItem(y(t)):null;if(!r||"null"===r)return null;try{return JSON.parse(r)}catch(e){return r}}finally{I(i)}},S=function(){var t=P();try{var n,i,r=0;for(arguments.length>=1&&("localStorage"===arguments[arguments.length-1]||"sessionStorage"===arguments[arguments.length-1])&&(r=1,I(arguments[arguments.length-1])),n=0;n0||(c.cookie="test").indexOf.call(c.cookie,"test")>-1)}catch(t){return e.$broadcast("LocalStorageModule.notification.error",t.message),!1}}(),T=function(t,n,s,l){if(i(n))return!1;if((a(n)||o(n))&&(n=u(n)),!O)return e.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var d="",p=new Date,f="";if(null===n?(p.setTime(p.getTime()+-864e5),d="; expires="+p.toGMTString(),n=""):r(s)&&0!==s?(p.setTime(p.getTime()+24*s*60*60*1e3),d="; expires="+p.toGMTString()):0!==v.expiry&&(p.setTime(p.getTime()+24*v.expiry*60*60*1e3),d="; expires="+p.toGMTString()),t){var h="; path="+v.path;v.domain&&(f="; domain="+v.domain),"boolean"==typeof l?!0===l&&(f+="; secure"):!0===v.secure&&(f+="; secure"),c.cookie=y(t)+"="+encodeURIComponent(n)+d+h+f}}catch(t){return e.$broadcast("LocalStorageModule.notification.error",t.message),!1}return!0},A=function(t){if(!O)return e.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var n=c.cookie&&c.cookie.split(";")||[],i=0;i-1&&n.splice(o,1)}e.className=n.join(" ")}function i(){return"rtl"===e.getComputedStyle(document.body).direction}function r(){return document.documentElement&&document.documentElement.scrollTop||document.body.scrollTop}function o(){return document.documentElement&&document.documentElement.scrollLeft||document.body.scrollLeft}function a(e){for(;e.lastChild;)e.removeChild(e.lastChild)}function s(e){if(null===e)return e;var t;if(Array.isArray(e)){t=[];for(var n=0;n0){for(var n=[],i=0;i=0?(n(document.body,ve.noOverflow),x(!1)):e>0&&document.body.className.indexOf(ve.noOverflow)<0&&(x(!0),t(document.body,ve.noOverflow))}function x(i){k.defaults.preventBodyShift&&(i&&document.documentElement.scrollHeight>document.documentElement.clientHeight?(be=pe,$e=e.getComputedStyle(document.body).top,t(document.body,ve.fixed),document.body.style.top=-pe+"px"):i||(pe=be,document.body.style.top=$e,n(document.body,ve.fixed),v()))}function C(e,t){for(var n=m.indexOf(t)+1;n200&&(we=e.timeStamp)&&!ye){var n=e.srcElement||e.target;!0===t.get("closableByDimmer")&&n===t.elements.modal&&S(t)}ye=!1}function N(e,t){if(Date.now()-xe>200&&(xe=Date.now()))for(var n=0;n-1?(N(t,function(e){return e.key===n}),!1):void 0}ke=!1}function L(e){var t=m[m.length-1],n=e.keyCode;if(n===f.LEFT||n===f.RIGHT){for(var i=t.__internal.buttons,r=0;rf.F1-1&&fe.indexOf(n)>-1)return e.preventDefault(),e.stopPropagation(),N(t,function(e){return e.key===n}),!1}function H(e,t){if(t)t.focus();else{var n=e.__internal.focus,i=n.element;switch(typeof n.element){case"number":e.__internal.buttons.length>n.element&&(i=!0===e.get("basic")?e.elements.reset[0]:e.__internal.buttons[n.element].element);break;case"string":i=e.elements.body.querySelector(n.element);break;case"function":i=n.element.call(e)}!0!==e.get("defaultFocusOff")&&(void 0!==i&&null!==i||0!==e.__internal.buttons.length)||(i=e.elements.reset[0]),i&&i.focus&&(i.focus(),n.select&&i.select&&i.select())}}function V(e,t){if(!t)for(var n=m.length-1;n>-1;n-=1)if(m[n].isModal()){t=m[n];break}if(t&&t.isModal()){var i,r=t.elements.reset[0],o=t.elements.reset[1],a=e.relatedTarget,s=t.elements.root.contains(a),l=e.srcElement||e.target;if(l===r&&!s||l===o&&a===r)return;l===o||l===document.body?i=r:l===r&&a===o?i=z(t):l===r&&s&&(i=z(t,!0)),H(t,i)}}function z(e,t){var n=[].slice.call(e.elements.dialog.querySelectorAll(h.tabbable));t&&n.reverse();for(var i=0;iIe?t.style.left=Pe+c+"px":t.offsetWidth>=Re&&(t.style.left=Pe-c+"px")}}(t,_e.elements.dialog,!_e.get("modal")&&!_e.get("pinned")))}function te(){if(_e){var e=_e;_e=null,n(document.body,ve.noSelection),n(e.elements.dialog,ve.capture),ye=!0,d("onresized",e)}}function ne(e){_e=null;var t=e.elements.dialog;"none"===t.style.maxWidth&&(t.style.maxWidth=t.style.minWidth=t.style.width=t.style.height=t.style.minHeight=t.style.left="",Pe=Number.Nan,Ie=Re=Fe=0)}function ie(){for(var e=0;e-1&&e.navigator.userAgent.indexOf("Chrome")<0,ge={dimmer:'
',modal:'
',dialog:'
',reset:'',commands:'
',header:'
',body:'
',content:'
',footer:'',buttons:{primary:'
',auxiliary:'
'},button:'',resizeHandle:'
'},ve={animationIn:"ajs-in",animationOut:"ajs-out",base:"alertify",basic:"ajs-basic",capture:"ajs-capture",closable:"ajs-closable",fixed:"ajs-fixed",frameless:"ajs-frameless",hidden:"ajs-hidden",maximize:"ajs-maximize",maximized:"ajs-maximized",maximizable:"ajs-maximizable",modeless:"ajs-modeless",movable:"ajs-movable",noSelection:"ajs-no-selection",noOverflow:"ajs-no-overflow",noPadding:"ajs-no-padding",pin:"ajs-pin",pinnable:"ajs-pinnable",prefix:"ajs-",resizable:"ajs-resizable",restore:"ajs-restore",shake:"ajs-shake",unpinned:"ajs-unpinned",noTransition:"ajs-no-transition"},$e="",be=0,ye=!1,we=0,xe=0,ke=!1,Ce=null,Ee=0,De=0,Se="pageX",Oe="pageY",Te=null,Ae=!1,Me=null,_e=null,Pe=Number.Nan,Ie=0,Re=0,Fe=0;return{__init:p,isOpen:function(){return this.__internal.isOpen},isModal:function(){return this.elements.root.className.indexOf(ve.modeless)<0},isMaximized:function(){return this.elements.root.className.indexOf(ve.maximized)>-1},isPinned:function(){return this.elements.root.className.indexOf(ve.unpinned)<0},maximize:function(){return this.isMaximized()||M(this),this},restore:function(){return this.isMaximized()&&_(this),this},pin:function(){return this.isPinned()||T(this),this},unpin:function(){return this.isPinned()&&A(this),this},bringToFront:function(){return C(0,this),this},moveTo:function(e,t){if(!isNaN(e)&&!isNaN(t)){d("onmove",this);var n=this.elements.dialog,r=n,o=0,a=0;n.style.left&&(o-=parseInt(n.style.left,10)),n.style.top&&(a-=parseInt(n.style.top,10));do{o+=r.offsetLeft,a+=r.offsetTop}while(r=r.offsetParent);var s=e-o,l=t-a;i()&&(s*=-1),n.style.left=s+"px",n.style.top=l+"px",d("onmoved",this)}return this},resizeTo:function(e,t){var n=parseFloat(e),i=parseFloat(t),r=/(\d*\.\d+|\d+)%/;if(!isNaN(n)&&!isNaN(i)&&!0===this.get("resizable")){d("onresize",this),(""+e).match(r)&&(n=n/100*document.documentElement.clientWidth),(""+t).match(r)&&(i=i/100*document.documentElement.clientHeight);var o=this.elements.dialog;"none"!==o.style.maxWidth&&(o.style.minWidth=(Re=o.offsetWidth)+"px"),o.style.maxWidth="none",o.style.minHeight=this.elements.header.offsetHeight+this.elements.footer.offsetHeight+"px",o.style.width=n+"px",o.style.height=i+"px",d("onresized",this)}return this},setting:function(e,t){var n=this,i=D(this,this.__internal.options,function(e,t,i){E(n,e,t,i)},e,t);if("get"===i.op)return i.found?i.value:void 0!==this.settings?D(this,this.settings,this.settingUpdated||function(){},e,t).value:void 0;if("set"===i.op){if(i.items.length>0)for(var r=this.settingUpdated||function(){},o=0;o0){var t=this;this.__internal.timer=setTimeout(function(){t.dismiss()},1e3*this.__internal.delay)}return this},setContent:function(n){if("string"==typeof n?(a(this.element),this.element.innerHTML=n):n instanceof e.HTMLElement&&this.element.firstChild!==n&&(a(this.element),this.element.appendChild(n)),this.__internal.closeButton){var i=document.createElement("span");t(i,p.close),i.setAttribute("data-close",!0),this.element.appendChild(i)}return this},dismissOthers:function(){return x.dismissAll(this),this}})}var c,d=[],p=h.notifier.classes,f=p.base;return{setting:function(e,t){if(i(this),void 0===t)return this.__internal[e];switch(e){case"position":this.__internal.position=t,s(this);break;case"delay":this.__internal.delay=t}return this},set:function(e,t){return this.setting(e,t),this},get:function(e){return this.setting(e)},create:function(e,t){i(this);var n=document.createElement("div");return n.className=p.message+("string"==typeof e&&""!==e?" "+p.prefix+e:""),l(n,t)},dismissAll:function(e){for(var t=d.slice(0),n=0;n-1&&(this.__origError=n,e.apply(this,[t,"_fix_for_ie_crossdomain__",r]))}}}),e("getResponseHeader",function(e){return function(t){return this.__fileApiXHR&&this.__fileApiXHR.getResponseHeader?this.__fileApiXHR.getResponseHeader(t):null==e?null:e.apply(this,[t])}}),e("getAllResponseHeaders",function(e){return function(){return this.__fileApiXHR&&this.__fileApiXHR.getAllResponseHeaders?this.__fileApiXHR.getAllResponseHeaders():null==e?null:e.apply(this)}}),e("abort",function(e){return function(){return this.__fileApiXHR&&this.__fileApiXHR.abort?this.__fileApiXHR.abort():null==e?null:e.apply(this)}}),e("setRequestHeader",function(e){return function(t,i){if("__setXHR_"===t){n(this);var r=i(this);r instanceof Function&&r(this)}else this.__requestHeaders=this.__requestHeaders||{},this.__requestHeaders[t]=i,e.apply(this,arguments)}}),e("send",function(e){return function(){var n=this;if(arguments[0]&&arguments[0].__isFileAPIShim){for(var i=arguments[0],r={url:n.__url,jsonp:!1,cache:!0,complete:function(e,i){e&&angular.isString(e)&&-1!==e.indexOf("#2174")&&(e=null),n.__completed=!0,!e&&n.__listeners.load&&n.__listeners.load({type:"load",loaded:n.__loaded,total:n.__total,target:n,lengthComputable:!0}),!e&&n.__listeners.loadend&&n.__listeners.loadend({type:"loadend",loaded:n.__loaded,total:n.__total,target:n,lengthComputable:!0}),"abort"===e&&n.__listeners.abort&&n.__listeners.abort({type:"abort",loaded:n.__loaded,total:n.__total,target:n,lengthComputable:!0}),void 0!==i.status&&t(n,"status",function(){return 0===i.status&&e&&"abort"!==e?500:i.status}),void 0!==i.statusText&&t(n,"statusText",function(){return i.statusText}),t(n,"readyState",function(){return 4}),void 0!==i.response&&t(n,"response",function(){return i.response});var r=i.responseText||(e&&0===i.status&&"abort"!==e?e:void 0);t(n,"responseText",function(){return r}),t(n,"response",function(){return r}),e&&t(n,"err",function(){return e}),n.__fileApiXHR=i,n.onreadystatechange&&n.onreadystatechange(),n.onload&&n.onload()},progress:function(e){if(e.target=n,n.__listeners.progress&&n.__listeners.progress(e),n.__total=e.total,n.__loaded=e.loaded,e.total===e.loaded){var t=this;setTimeout(function(){n.__completed||(n.getAllResponseHeaders=function(){},t.complete(null,{status:204,statusText:"No Content"}))},FileAPI.noContentTimeout||1e4)}},headers:n.__requestHeaders,data:{},files:{}},o=0;o-1){i=a.substring(0,o+1);break}null==FileAPI.staticPath&&(FileAPI.staticPath=i),s.setAttribute("src",n||i+"FileAPI.min.js"),document.getElementsByTagName("head")[0].appendChild(s)}FileAPI.ngfFixIE=function(n,i,r){if(!e())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';n.bind("mouseenter",function(){var e=i.parent();n.attr("disabled")?e&&e.removeClass("js-fileapi-wrapper"):(i.attr("__ngf_flash_")||(i.unbind("change"),i.unbind("click"),i.bind("change",function(e){o.apply(this,[e]),r.apply(this,[e])}),i.attr("__ngf_flash_","true")),e.addClass("js-fileapi-wrapper"),function(e){return"input"===e[0].tagName.toLowerCase()&&e.attr("type")&&"file"===e.attr("type").toLowerCase()}(n)||(e.css("position","absolute").css("top",t(n[0]).top+"px").css("left",t(n[0]).left+"px").css("width",n[0].offsetWidth+"px").css("height",n[0].offsetHeight+"px").css("filter","alpha(opacity=0)").css("display",n.css("display")).css("overflow","hidden").css("z-index","900000").css("visibility","visible"),i.css("width",n[0].offsetWidth+"px").css("height",n[0].offsetHeight+"px").css("position","absolute").css("top","0px").css("left","0px")))});var o=function(e){for(var t=FileAPI.getFiles(e),n=0;n0},this.rename=function(e,t){return e.ngfName=t,e},this.jsonBlob=function(e){null==e||angular.isString(e)||(e=JSON.stringify(e));var t=new window.Blob([e],{type:"application/json"});return t._ngfBlob=!0,t},this.json=function(e){return angular.toJson(e)},this.isFile=function(e){return null!=e&&(e instanceof window.Blob||e.flashId&&e.name&&e.size)},this.upload=function(e,t){function n(t,n){if(t._ngfBlob)return t;if(e._file=e._file||t,null!=e._start&&a){e._end&&e._end>=t.size&&(e._finished=!0,e._end=t.size);var i=t.slice(e._start,e._end||t.size);return i.name=t.name,i.ngfName=t.ngfName,e._chunkSize&&(n.append("_chunkSize",e._chunkSize),n.append("_currentChunkSize",e._end-e._start),n.append("_chunkNumber",Math.floor(e._start/e._chunkSize)),n.append("_totalSize",e._file.size)),i}return t}function s(t,i,r){if(void 0!==i)if(angular.isDate(i)&&(i=i.toISOString()),angular.isString(i))t.append(r,i);else if(o.isFile(i)){var a=n(i,t),l=r.split(",");l[1]&&(a.ngfName=l[1].replace(/^\s+|\s+$/g,""),r=l[0]),e._fileKey=e._fileKey||r,t.append(r,a,a.ngfName||a.name)}else if(angular.isObject(i)){if(i.$$ngfCircularDetection)throw"ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: "+r;i.$$ngfCircularDetection=!0;try{for(var u in i)if(i.hasOwnProperty(u)&&"$$ngfCircularDetection"!==u){var c=null==e.objectKey?"[i]":e.objectKey;i.length&&parseInt(u)>-1&&(c=null==e.arrayKey?c:e.arrayKey),s(t,i[u],r+c.replace(/[ik]/g,u))}}finally{delete i.$$ngfCircularDetection}}else t.append(r,i)}return t||(e=r(e)),e._isDigested||(e._isDigested=!0,e._chunkSize=o.translateScalars(e.resumeChunkSize),e._chunkSize=e._chunkSize?parseInt(e._chunkSize.toString()):null,e.headers=e.headers||{},e.headers["Content-Type"]=void 0,e.transformRequest=e.transformRequest?angular.isArray(e.transformRequest)?e.transformRequest:[e.transformRequest]:[],e.transformRequest.push(function(t){var n,i=new window.FormData;for(n in t=t||e.fields||{},e.file&&(t.file=e.file),t)if(t.hasOwnProperty(n)){var r=t[n];e.formDataAppender?e.formDataAppender(i,n,r):s(i,r,n)}return i})),i(e)},this.http=function(t){return(t=r(t)).transformRequest=t.transformRequest||function(t){return window.ArrayBuffer&&t instanceof window.ArrayBuffer||t instanceof window.Blob?t:e.defaults.transformRequest[0].apply(this,arguments)},t._chunkSize=o.translateScalars(t.resumeChunkSize),t._chunkSize=t._chunkSize?parseInt(t._chunkSize.toString()):null,i(t)},this.translateScalars=function(e){if(angular.isString(e)){if(e.search(/kb/i)===e.length-2)return parseFloat(1024*e.substring(0,e.length-2));if(e.search(/mb/i)===e.length-2)return parseFloat(1048576*e.substring(0,e.length-2));if(e.search(/gb/i)===e.length-2)return parseFloat(1073741824*e.substring(0,e.length-2));if(e.search(/b/i)===e.length-1)return parseFloat(e.substring(0,e.length-1));if(e.search(/s/i)===e.length-1)return parseFloat(e.substring(0,e.length-1));if(e.search(/m/i)===e.length-1)return parseFloat(60*e.substring(0,e.length-1));if(e.search(/h/i)===e.length-1)return parseFloat(3600*e.substring(0,e.length-1))}return e},this.urlToBlob=function(n){var i=t.defer();return e({url:n,method:"get",responseType:"arraybuffer"}).then(function(e){var t=new Uint8Array(e.data),r=e.headers("content-type")||"image/WebP",o=new window.Blob([t],{type:r}),a=n.match(/.*\/(.+?)(\?.*)?$/);a.length>1&&(o.name=a[1]),i.resolve(o)},function(e){i.reject(e)}),i.promise},this.setDefaults=function(e){this.defaults=e||{}},this.defaults={},this.version=ngFileUpload.version}]),ngFileUpload.service("Upload",["$parse","$timeout","$compile","$q","UploadExif",function(e,t,n,i,r){function o(e,t,n){var r=[l.emptyPromise()];return angular.forEach(e,function(i,o){0===i.type.indexOf("image/jpeg")&&l.attrGetter("ngfFixOrientation",t,n,{$file:i})&&r.push(l.happyPromise(l.applyExifRotation(i),i).then(function(t){e.splice(o,1,t)}))}),i.all(r)}function a(e,t,n,r){var o=l.attrGetter("ngfResize",t,n);if(!o||!l.isResizeSupported()||!e.length)return l.emptyPromise();if(o instanceof Function){var a=i.defer();return o(e).then(function(i){s(i,e,t,n,r).then(function(e){a.resolve(e)},function(e){a.reject(e)})},function(e){a.reject(e)})}return s(o,e,t,n,r)}function s(e,t,n,r,o){function a(i,a){if(0===i.type.indexOf("image")){if(e.pattern&&!l.validatePattern(i,e.pattern))return;e.resizeIf=function(e,t){return l.attrGetter("ngfResizeIf",n,r,{$width:e,$height:t,$file:i})};var u=l.resize(i,e);s.push(u),u.then(function(e){t.splice(a,1,e)},function(e){i.$error="resize",(i.$errorMessages=i.$errorMessages||{}).resize=!0,i.$errorParam=(e?(e.message?e.message:e)+": ":"")+(i&&i.name),o.$ngfValidations.push({name:"resize",valid:!1}),l.applyModelValidation(o,t)})}}for(var s=[l.emptyPromise()],u=0;u-1},l.emptyPromise=function(){var e=i.defer(),n=arguments;return t(function(){e.resolve.apply(e,n)}),e.promise},l.rejectPromise=function(){var e=i.defer(),n=arguments;return t(function(){e.reject.apply(e,n)}),e.promise},l.happyPromise=function(e,n){var r=i.defer();return e.then(function(e){r.resolve(e)},function(e){t(function(){throw e}),r.resolve(n)}),r.promise},l.updateModel=function(n,i,r,s,u,c,d){function p(o,a,u,d,p){i.$$ngfPrevValidFiles=o,i.$$ngfPrevInvalidFiles=a;var f=o&&o.length?o[0]:null,h=a&&a.length?a[0]:null;n&&(l.applyModelValidation(n,o),n.$setViewValue(p?f:o)),s&&e(s)(r,{$files:o,$file:f,$newFiles:u,$duplicateFiles:d,$invalidFiles:a,$invalidFile:h,$event:c});var m=l.attrGetter("ngfModelInvalid",i);m&&t(function(){e(m).assign(r,p?h:a)}),t(function(){})}function f(){function e(){t(function(){p(y?m.concat(b):b,y?g.concat($):$,u,v,w)},k&&k.debounce?k.debounce.change||k.debounce:0)}var o=x?h:b;a(o,i,r,n).then(function(){x?l.validate(h,y?m.length:0,n,i,r).then(function(t){b=t.validsFiles,$=t.invalidsFiles,e()}):e()},function(){for(var t=0;t-1&&(b.splice(i,1),$.push(n)),e()}}})}var h,m,g,v=[],$=[],b=[];m=i.$$ngfPrevValidFiles||[],g=i.$$ngfPrevInvalidFiles||[],n&&n.$modelValue&&(m=function(e){return angular.isArray(e)?e:[e]}(n.$modelValue));var y=l.attrGetter("ngfKeep",i,r);h=(u||[]).slice(0),("distinct"===y||!0===l.attrGetter("ngfKeepDistinct",i,r))&&function(){function e(e,t){return e.name===t.name&&(e.$ngfOrigSize||e.size)===(t.$ngfOrigSize||t.size)&&e.type===t.type}function t(t){var n;for(n=0;n2){var n=i.defaults.androidFixMinorVersion||4;return parseInt(t[1])<4||parseInt(t[1])===n&&parseInt(t[2])'),n=angular.element("");return n.css("visibility","hidden").css("position","absolute").css("overflow","hidden").css("width","0px").css("height","0px").css("border","none").css("margin","0px").css("padding","0px").attr("tabindex","-1"),f(e,n),a.push({el:t,ref:n}),document.body.appendChild(n.append(e)[0]),e}()),b.bind("change",p),c()?t.bind("click",h):t.bind("click touchstart touchend",function(n){if(t.attr("disabled"))return!1;if(!m("ngfSelectDisabled",e)){var i=function(e){var t=e.changedTouches||e.originalEvent&&e.originalEvent.changedTouches;if(t){if("touchstart"===e.type)return $=t[0].clientX,v=t[0].clientY,!0;if("touchend"===e.type){var n=t[0].clientX,i=t[0].clientY;if(Math.abs(n-$)>20||Math.abs(i-v)>20)return e.stopPropagation(),e.preventDefault(),!1}return!0}}(n);if(null!=i)return i;h(n);try{c()||document.body.contains(b[0])||(a.push({el:t,ref:b.parent()}),document.body.appendChild(b.parent()[0]),b.bind("change",p))}catch(e){}return r(navigator.userAgent)?setTimeout(function(){b[0].click()},0):b[0].click(),!1}}),-1!==navigator.appVersion.indexOf("MSIE 10")&&b.bind("click",function e(t){if(b&&!b.attr("__ngf_ie10_Fix_")){if(!b[0].parentNode)return void(b=null);t.preventDefault(),t.stopPropagation(),b.unbind("click");var n=b.clone();return b.replaceWith(n),(b=n).attr("__ngf_ie10_Fix_","true"),b.bind("change",p),b.bind("click",e),b[0].click(),!1}b.removeAttr("__ngf_ie10_Fix_")}),i&&i.$formatters.push(function(e){return(null==e||0===e.length)&&b.val()&&b.val(null),e}),e.$on("$destroy",function(){c()||b.parent().remove(),angular.forEach(g,function(e){e()})}),s(function(){for(var e=0;e-1&&c.height&&c.height.indexOf("px")>-1&&(u={width:parseInt(c.width.slice(0,-2)),height:parseInt(c.height.slice(0,-2))})}return angular.isString(t)?(i.removeClass("ng-hide"),s?i.css("background-image","url('"+t+"')"):i.attr("src",t)):void(!t||!t.type||0!==t.type.search(function(e){return"img"===e.tagName.toLowerCase()?"image":"audio"===e.tagName.toLowerCase()?"audio":"video"===e.tagName.toLowerCase()?"video":/./}(i[0]))||s&&0!==t.type.indexOf("image")?i.addClass("ng-hide"):u&&e.isResizeSupported()?(u.resizeIf=function(i,o){return e.attrGetter("ngfResizeIf",r,n,{$width:i,$height:o,$file:t})},e.resize(t,u).then(function(e){l(e)},function(e){throw e})):l(t))});n.$on("$destroy",function(){t()})})}ngFileUpload.service("UploadDataUrl",["UploadBase","$timeout","$q",function(e,t,n){var i=e;return i.base64DataUrl=function(e){if(angular.isArray(e)){var t=n.defer(),r=0;return angular.forEach(e,function(n){i.dataUrl(n,!0).finally(function(){if(++r===e.length){var n=[];angular.forEach(e,function(e){n.push(e.$ngfDataUrl)}),t.resolve(n,e)}})}),t.promise}return i.dataUrl(e,!0)},i.dataUrl=function(e,r){if(!e)return i.emptyPromise(e,e);if(r&&null!=e.$ngfDataUrl||!r&&null!=e.$ngfBlobUrl)return i.emptyPromise(r?e.$ngfDataUrl:e.$ngfBlobUrl,e);var o=r?e.$$ngfDataUrlPromise:e.$$ngfBlobUrlPromise;if(o)return o;var a=n.defer();return t(function(){if(window.FileReader&&e&&(!window.FileAPI||-1===navigator.userAgent.indexOf("MSIE 8")||e.size<2e4)&&(!window.FileAPI||-1===navigator.userAgent.indexOf("MSIE 9")||e.size<4e6)){var n=window.URL||window.webkitURL;if(n&&n.createObjectURL&&!r){var o;try{o=n.createObjectURL(e)}catch(n){return void t(function(){e.$ngfBlobUrl="",a.reject()})}t(function(){if(e.$ngfBlobUrl=o,o){a.resolve(o,e),i.blobUrls=i.blobUrls||[],i.blobUrlsTotalSize=i.blobUrlsTotalSize||0,i.blobUrls.push({url:o,size:e.size}),i.blobUrlsTotalSize+=e.size||0;for(var t=i.defaults.blobUrlsMaxMemory||268435456,r=i.defaults.blobUrlsMaxQueueSize||200;(i.blobUrlsTotalSize>t||i.blobUrls.length>r)&&i.blobUrls.length>1;){var s=i.blobUrls.splice(0,1)[0];n.revokeObjectURL(s.url),i.blobUrlsTotalSize-=s.size}}})}else{var s=new FileReader;s.onload=function(n){t(function(){e.$ngfDataUrl=n.target.result,a.resolve(n.target.result,e),t(function(){delete e.$ngfDataUrl},1e3)})},s.onerror=function(){t(function(){e.$ngfDataUrl="",a.reject()})},s.readAsDataURL(e)}}else t(function(){e[r?"$ngfDataUrl":"$ngfBlobUrl"]="",a.reject()})}),(o=r?e.$$ngfDataUrlPromise=a.promise:e.$$ngfBlobUrlPromise=a.promise).finally(function(){delete e[r?"$$ngfDataUrlPromise":"$$ngfBlobUrlPromise"]}),o},i}]),ngFileUpload.directive("ngfSrc",["Upload","$timeout",function(t,n){return{restrict:"AE",link:function(i,r,o){e(t,n,i,r,o,"ngfSrc",t.attrGetter("ngfResize",o,i),!1)}}}]),ngFileUpload.directive("ngfBackground",["Upload","$timeout",function(t,n){return{restrict:"AE",link:function(i,r,o){e(t,n,i,r,o,"ngfBackground",t.attrGetter("ngfResize",o,i),!0)}}}]),ngFileUpload.directive("ngfThumbnail",["Upload","$timeout",function(t,n){return{restrict:"AE",link:function(i,r,o){var a=t.attrGetter("ngfSize",o,i);e(t,n,i,r,o,"ngfThumbnail",a,t.attrGetter("ngfAsBackground",o,i))}}}]),ngFileUpload.config(["$compileProvider",function(e){e.imgSrcSanitizationWhitelist&&e.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/),e.aHrefSanitizationWhitelist&&e.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/)}]),ngFileUpload.filter("ngfDataUrl",["UploadDataUrl","$sce",function(e,t){return function(n,i,r){if(angular.isString(n))return t.trustAsResourceUrl(n);var o=n&&((i?n.$ngfDataUrl:n.$ngfBlobUrl)||n.$ngfDataUrl);return n&&!o?(!n.$ngfDataUrlFilterInProgress&&angular.isObject(n)&&(n.$ngfDataUrlFilterInProgress=!0,e.dataUrl(n,i)),""):(n&&delete n.$ngfDataUrlFilterInProgress,(n&&o?r?t.trustAsResourceUrl(o):o:n)||"")}}])}(),ngFileUpload.service("UploadValidate",["UploadDataUrl","$q","$timeout",function(e,t,n){var i=e;return i.validatePattern=function(e,t){if(!t)return!0;var n=function e(t){var n="",i=[];if(t.length>2&&"/"===t[0]&&"/"===t[t.length-1])n=t.substring(1,t.length-1);else{var r=t.split(",");if(r.length>1)for(var o=0;o|:\\-]","g"),"\\$&")+"$").replace(/\\\*/g,".*").replace(/\\\?/g,"."))}return{regexp:n,excludes:i}}(t),i=!0;if(n.regexp&&n.regexp.length){var r=new RegExp(n.regexp,"i");i=null!=e.type&&r.test(e.type)||null!=e.name&&r.test(e.name)}for(var o=n.excludes.length;o--;){var a=new RegExp(n.excludes[o],"i");i=i&&(null==e.type||a.test(e.type))&&(null==e.name||a.test(e.name))}return i},i.ratioToFloat=function(e){var t=e.toString(),n=t.search(/[x:]/i);return n>-1?parseFloat(t.substring(0,n))/parseFloat(t.substring(n+1)):parseFloat(t)},i.registerModelChangeValidator=function(e,t,n){e&&e.$formatters.push(function(r){if(e.$dirty){var o=r;r&&!angular.isArray(r)&&(o=[r]),i.validate(o,0,e,t,n).then(function(){i.applyModelValidation(e,o)})}return r})},i.applyModelValidation=function(e,t){(function(e,t){null==t||e.$dirty||(e.$setDirty?e.$setDirty():e.$dirty=!0)})(e,t),angular.forEach(e.$ngfValidations,function(t){e.$setValidity(t.name,t.valid)})},i.getValidationAttr=function(e,t,n,r,o){var a="ngf"+n[0].toUpperCase()+n.substr(1),s=i.attrGetter(a,e,t,{$file:o});if(null==s&&(s=i.attrGetter("ngfValidate",e,t,{$file:o}))){var l=(r||n).split(".");s=s[l[0]],l.length>1&&(s=s&&s[l[1]])}return s},i.validate=function(e,n,r,o,a){function s(t,n,s){if(e){for(var l=e.length,u=null;l--;){var f=e[l];if(f){var h=i.getValidationAttr(o,a,t,n,f);null!=h&&(s(f,h,l)||(-1===c.indexOf(t)?(f.$error=t,(f.$errorMessages=f.$errorMessages||{})[t]=!0,f.$errorParam=h,-1===p.indexOf(f)&&p.push(f),d||e.splice(l,1),u=!1):e.splice(l,1)))}}null!==u&&r.$ngfValidations.push({name:t,valid:u})}}function l(n,s,l,f,h){function m(t,i,r){function o(o){if(o())if(-1===c.indexOf(n)){if(i.$error=n,(i.$errorMessages=i.$errorMessages||{})[n]=!0,i.$errorParam=r,-1===p.indexOf(i)&&p.push(i),!d){var a=e.indexOf(i);a>-1&&e.splice(a,1)}t.resolve(!1)}else{var s=e.indexOf(i);s>-1&&e.splice(s,1),t.resolve(!0)}else t.resolve(!0)}null!=r?f(i,r).then(function(e){o(function(){return!h(e,r)})},function(){o(function(){return u("ngfValidateForce",{$file:i})})}):t.resolve(!0)}var g=[i.emptyPromise(!0)];e&&(e=void 0===e.length?[e]:e,angular.forEach(e,function(e){var r=t.defer();return g.push(r.promise),!l||null!=e.type&&0===e.type.search(l)?void("dimensions"===n&&null!=i.attrGetter("ngfDimensions",o)?i.imageDimensions(e).then(function(t){m(r,e,u("ngfDimensions",{$file:e,$width:t.width,$height:t.height}))},function(){r.resolve(!1)}):"duration"===n&&null!=i.attrGetter("ngfDuration",o)?i.mediaDuration(e).then(function(t){m(r,e,u("ngfDuration",{$file:e,$duration:t}))},function(){r.resolve(!1)}):m(r,e,i.getValidationAttr(o,a,n,s,e))):void r.resolve(!0)}));var v=t.defer();return t.all(g).then(function(e){for(var t=!0,i=0;i=i.translateScalars(t)}),s("maxSize","size.max",function(e,t){return e.size-.1<=i.translateScalars(t)});var f=0;if(s("maxTotalSize",null,function(t,n){return!((f+=t.size)>i.translateScalars(n))||(e.splice(0,e.length),!1)}),s("validateFn",null,function(e,t){return!0===t||null===t||""===t}),!e.length)return i.emptyPromise({validFiles:[],invalidFiles:p});var h=t.defer(),m=[];return m.push(l("maxHeight","height.max",/image/,this.imageDimensions,function(e,t){return e.height<=t})),m.push(l("minHeight","height.min",/image/,this.imageDimensions,function(e,t){return e.height>=t})),m.push(l("maxWidth","width.max",/image/,this.imageDimensions,function(e,t){return e.width<=t})),m.push(l("minWidth","width.min",/image/,this.imageDimensions,function(e,t){return e.width>=t})),m.push(l("dimensions",null,/image/,function(e,t){return i.emptyPromise(t)},function(e){return e})),m.push(l("ratio",null,/image/,this.imageDimensions,function(e,t){for(var n=t.toString().split(","),r=!1,o=0;o-1e-4})),m.push(l("maxDuration","duration.max",/audio|video/,this.mediaDuration,function(e,t){return e<=i.translateScalars(t)})),m.push(l("minDuration","duration.min",/audio|video/,this.mediaDuration,function(e,t){return e>=i.translateScalars(t)})),m.push(l("duration",null,/audio|video/,function(e,t){return i.emptyPromise(t)},function(e){return e})),m.push(l("validateAsyncFn",null,null,function(e,t){return t},function(e){return!0===e||null===e||""===e})),t.all(m).then(function(){if(d)for(var t=0;tn+i}),h.resolve({validFiles:e,invalidFiles:p})}),h.promise},i.imageDimensions=function(e){if(e.$ngfWidth&&e.$ngfHeight){var r=t.defer();return n(function(){r.resolve({width:e.$ngfWidth,height:e.$ngfHeight})}),r.promise}if(e.$ngfDimensionPromise)return e.$ngfDimensionPromise;var o=t.defer();return n(function(){return 0!==e.type.indexOf("image")?void o.reject("not image"):void i.dataUrl(e).then(function(t){function i(){var t=a[0].naturalWidth||a[0].clientWidth,n=a[0].naturalHeight||a[0].clientHeight;a.remove(),e.$ngfWidth=t,e.$ngfHeight=n,o.resolve({width:t,height:n})}function r(){a.remove(),o.reject("load error")}var a=angular.element("").attr("src",t).css("visibility","hidden").css("position","fixed").css("max-width","none !important").css("max-height","none !important");a.on("load",i),a.on("error",r);var s=0;(function e(){n(function(){a[0].parentNode&&(a[0].clientWidth?i():s++>10?r():e())},1e3)})(),angular.element(document.getElementsByTagName("body")[0]).append(a)},function(){o.reject("load error")})}),e.$ngfDimensionPromise=o.promise,e.$ngfDimensionPromise.finally(function(){delete e.$ngfDimensionPromise}),e.$ngfDimensionPromise},i.mediaDuration=function(e){if(e.$ngfDuration){var r=t.defer();return n(function(){r.resolve(e.$ngfDuration)}),r.promise}if(e.$ngfDurationPromise)return e.$ngfDurationPromise;var o=t.defer();return n(function(){return 0!==e.type.indexOf("audio")&&0!==e.type.indexOf("video")?void o.reject("not media"):void i.dataUrl(e).then(function(t){function i(){var t=a[0].duration;e.$ngfDuration=t,a.remove(),o.resolve(t)}function r(){a.remove(),o.reject("load error")}var a=angular.element(0===e.type.indexOf("audio")?"