feat: add logging, marketplace, and admin enhancements
Database & Migrations: - Add application_logs table migration for hybrid cloud logging - Add companies table migration and restructure vendor relationships Logging System: - Implement hybrid logging system (database + file) - Add log_service for centralized log management - Create admin logs page with filtering and viewing capabilities - Add init_log_settings.py script for log configuration - Enhance core logging with database integration Marketplace Integration: - Add marketplace admin page with product management - Create marketplace vendor page with product listings - Implement marketplace.js for both admin and vendor interfaces - Add marketplace integration documentation Admin Enhancements: - Add imports management page and functionality - Create settings page for admin configuration - Add vendor themes management page - Enhance vendor detail and edit pages - Improve code quality dashboard and violation details - Add logs viewing and management - Update icons guide and shared icon system Architecture & Documentation: - Document frontend structure and component architecture - Document models structure and relationships - Add vendor-in-token architecture documentation - Add vendor RBAC (role-based access control) documentation - Document marketplace integration patterns - Update architecture patterns documentation Infrastructure: - Add platform static files structure (css, img, js) - Move architecture_scan.py to proper models location - Update model imports and registrations - Enhance exception handling - Update dependency injection patterns UI/UX: - Improve vendor edit interface - Update admin user interface - Enhance page templates documentation - Add vendor marketplace interface
This commit is contained in:
@@ -18,8 +18,9 @@ function codeQualityViolationDetail(violationId) {
|
||||
updating: false,
|
||||
commenting: false,
|
||||
newComment: '',
|
||||
newStatus: '',
|
||||
assignedTo: '',
|
||||
assignUserId: '',
|
||||
resolutionNote: '',
|
||||
ignoreReason: '',
|
||||
|
||||
async init() {
|
||||
await this.loadViolation();
|
||||
@@ -30,10 +31,8 @@ function codeQualityViolationDetail(violationId) {
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
const response = await apiClient.get(`/api/v1/admin/code-quality/violations/${this.violationId}`);
|
||||
this.violation = response.data;
|
||||
this.newStatus = this.violation.status;
|
||||
this.assignedTo = this.violation.assigned_to || '';
|
||||
const response = await apiClient.get(`/admin/code-quality/violations/${this.violationId}`);
|
||||
this.violation = response;
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Load Violation');
|
||||
this.error = error.response?.data?.message || 'Failed to load violation details';
|
||||
@@ -42,41 +41,75 @@ function codeQualityViolationDetail(violationId) {
|
||||
}
|
||||
},
|
||||
|
||||
async updateStatus() {
|
||||
if (!this.newStatus) return;
|
||||
async assignViolation() {
|
||||
const userId = parseInt(this.assignUserId);
|
||||
if (!userId || isNaN(userId)) {
|
||||
Utils.showToast('Please enter a valid user ID', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
this.updating = true;
|
||||
|
||||
try {
|
||||
await apiClient.patch(`/api/v1/admin/code-quality/violations/${this.violationId}/status`, {
|
||||
status: this.newStatus
|
||||
await apiClient.post(`/admin/code-quality/violations/${this.violationId}/assign`, {
|
||||
user_id: userId,
|
||||
priority: 'medium'
|
||||
});
|
||||
|
||||
Utils.showToast('Status updated successfully', 'success');
|
||||
this.assignUserId = '';
|
||||
Utils.showToast('Violation assigned successfully', 'success');
|
||||
await this.loadViolation();
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Update Status');
|
||||
Utils.showToast(error.response?.data?.message || 'Failed to update status', 'error');
|
||||
window.LogConfig.logError(error, 'Assign Violation');
|
||||
Utils.showToast(error.message || 'Failed to assign violation', 'error');
|
||||
} finally {
|
||||
this.updating = false;
|
||||
}
|
||||
},
|
||||
|
||||
async assignViolation() {
|
||||
if (!this.assignedTo) return;
|
||||
async resolveViolation() {
|
||||
if (!this.resolutionNote.trim()) {
|
||||
Utils.showToast('Please enter a resolution note', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
this.updating = true;
|
||||
|
||||
try {
|
||||
await apiClient.patch(`/api/v1/admin/code-quality/violations/${this.violationId}/assign`, {
|
||||
assigned_to: this.assignedTo
|
||||
await apiClient.post(`/admin/code-quality/violations/${this.violationId}/resolve`, {
|
||||
resolution_note: this.resolutionNote
|
||||
});
|
||||
|
||||
Utils.showToast('Violation assigned successfully', 'success');
|
||||
this.resolutionNote = '';
|
||||
Utils.showToast('Violation resolved successfully', 'success');
|
||||
await this.loadViolation();
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Assign Violation');
|
||||
Utils.showToast(error.response?.data?.message || 'Failed to assign violation', 'error');
|
||||
window.LogConfig.logError(error, 'Resolve Violation');
|
||||
Utils.showToast(error.message || 'Failed to resolve violation', 'error');
|
||||
} finally {
|
||||
this.updating = false;
|
||||
}
|
||||
},
|
||||
|
||||
async ignoreViolation() {
|
||||
if (!this.ignoreReason.trim()) {
|
||||
Utils.showToast('Please enter a reason for ignoring', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
this.updating = true;
|
||||
|
||||
try {
|
||||
await apiClient.post(`/admin/code-quality/violations/${this.violationId}/ignore`, {
|
||||
reason: this.ignoreReason
|
||||
});
|
||||
|
||||
this.ignoreReason = '';
|
||||
Utils.showToast('Violation ignored successfully', 'success');
|
||||
await this.loadViolation();
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Ignore Violation');
|
||||
Utils.showToast(error.message || 'Failed to ignore violation', 'error');
|
||||
} finally {
|
||||
this.updating = false;
|
||||
}
|
||||
@@ -88,7 +121,7 @@ function codeQualityViolationDetail(violationId) {
|
||||
this.commenting = true;
|
||||
|
||||
try {
|
||||
await apiClient.post(`/api/v1/admin/code-quality/violations/${this.violationId}/comments`, {
|
||||
await apiClient.post(`/admin/code-quality/violations/${this.violationId}/comments`, {
|
||||
comment: this.newComment
|
||||
});
|
||||
|
||||
@@ -97,7 +130,7 @@ function codeQualityViolationDetail(violationId) {
|
||||
await this.loadViolation();
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Add Comment');
|
||||
Utils.showToast(error.response?.data?.message || 'Failed to add comment', 'error');
|
||||
Utils.showToast(error.message || 'Failed to add comment', 'error');
|
||||
} finally {
|
||||
this.commenting = false;
|
||||
}
|
||||
@@ -222,48 +255,72 @@ function codeQualityViolationDetail(violationId) {
|
||||
<div class="p-6 bg-white rounded-lg shadow-xs dark:bg-gray-800">
|
||||
<h4 class="text-lg font-semibold text-gray-700 dark:text-gray-200 mb-4">Manage Violation</h4>
|
||||
|
||||
<div class="grid gap-4 md:grid-cols-2 mb-6">
|
||||
<!-- Update Status -->
|
||||
<!-- Assign Section -->
|
||||
<div class="mb-6" x-show="violation.status === 'open' || violation.status === 'assigned'">
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-2">Assign to User</label>
|
||||
<div class="flex gap-2">
|
||||
<input x-model="assignUserId"
|
||||
type="number"
|
||||
placeholder="User ID"
|
||||
class="flex-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray form-input rounded-md">
|
||||
<button @click="assignViolation()"
|
||||
:disabled="updating || !assignUserId"
|
||||
class="px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg active:bg-purple-600 hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<span x-show="!updating">Assign</span>
|
||||
<span x-show="updating">Assigning...</span>
|
||||
</button>
|
||||
</div>
|
||||
<p x-show="violation.assigned_to" class="mt-1 text-xs text-gray-500">
|
||||
Currently assigned to user ID: <span x-text="violation.assigned_to"></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="grid gap-4 md:grid-cols-2" x-show="violation.status === 'open' || violation.status === 'assigned'">
|
||||
<!-- Resolve -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-2">Status</label>
|
||||
<div class="flex gap-2">
|
||||
<select x-model="newStatus"
|
||||
class="flex-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray form-select rounded-md">
|
||||
<option value="open">Open</option>
|
||||
<option value="assigned">Assigned</option>
|
||||
<option value="resolved">Resolved</option>
|
||||
<option value="ignored">Ignored</option>
|
||||
</select>
|
||||
<button @click="updateStatus()"
|
||||
:disabled="updating || newStatus === violation.status"
|
||||
class="px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg active:bg-purple-600 hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<span x-show="!updating">Update</span>
|
||||
<span x-show="updating">Updating...</span>
|
||||
</button>
|
||||
</div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-2">Resolve Violation</label>
|
||||
<textarea x-model="resolutionNote"
|
||||
rows="2"
|
||||
placeholder="Resolution note..."
|
||||
class="block w-full mt-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray form-textarea rounded-md"></textarea>
|
||||
<button @click="resolveViolation()"
|
||||
:disabled="updating || !resolutionNote.trim()"
|
||||
class="mt-2 w-full px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-green-600 border border-transparent rounded-lg active:bg-green-600 hover:bg-green-700 focus:outline-none focus:shadow-outline-green disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<span x-show="!updating">Mark as Resolved</span>
|
||||
<span x-show="updating">Resolving...</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Assign -->
|
||||
<!-- Ignore -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-2">Assign To</label>
|
||||
<div class="flex gap-2">
|
||||
<input x-model="assignedTo"
|
||||
type="text"
|
||||
placeholder="Username or email"
|
||||
class="flex-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray form-input rounded-md">
|
||||
<button @click="assignViolation()"
|
||||
:disabled="updating || !assignedTo"
|
||||
class="px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg active:bg-purple-600 hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<span x-show="!updating">Assign</span>
|
||||
<span x-show="updating">Assigning...</span>
|
||||
</button>
|
||||
</div>
|
||||
<p x-show="violation.assigned_to" class="mt-1 text-xs text-gray-500">
|
||||
Currently assigned to: <span x-text="violation.assigned_to"></span>
|
||||
</p>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-2">Ignore Violation</label>
|
||||
<textarea x-model="ignoreReason"
|
||||
rows="2"
|
||||
placeholder="Reason for ignoring..."
|
||||
class="block w-full mt-1 text-sm dark:text-gray-300 dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray form-textarea rounded-md"></textarea>
|
||||
<button @click="ignoreViolation()"
|
||||
:disabled="updating || !ignoreReason.trim()"
|
||||
class="mt-2 w-full px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-gray-600 border border-transparent rounded-lg active:bg-gray-600 hover:bg-gray-700 focus:outline-none focus:shadow-outline-gray disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<span x-show="!updating">Ignore Violation</span>
|
||||
<span x-show="updating">Ignoring...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Resolution Info (for resolved/ignored) -->
|
||||
<div x-show="violation.status === 'resolved' || violation.status === 'ignored'" class="p-4 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<p class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
This violation has been <span x-text="violation.status"></span>
|
||||
</p>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400" x-show="violation.resolution_note">
|
||||
Note: <span x-text="violation.resolution_note"></span>
|
||||
</p>
|
||||
<p class="text-sm text-gray-500 mt-1" x-show="violation.resolved_at">
|
||||
<span x-text="formatDate(violation.resolved_at)"></span> by user ID <span x-text="violation.resolved_by"></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Comments Section -->
|
||||
<div>
|
||||
<h5 class="text-md font-semibold text-gray-700 dark:text-gray-200 mb-3">Comments</h5>
|
||||
@@ -293,7 +350,9 @@ function codeQualityViolationDetail(violationId) {
|
||||
<template x-for="comment in (violation.comments || [])" :key="comment.id">
|
||||
<div class="p-3 bg-gray-50 dark:bg-gray-900 rounded-lg">
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<p class="text-sm font-medium text-gray-700 dark:text-gray-300" x-text="comment.user"></p>
|
||||
<p class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
User ID: <span x-text="comment.user_id"></span>
|
||||
</p>
|
||||
<p class="text-xs text-gray-500" x-text="formatDate(comment.created_at)"></p>
|
||||
</div>
|
||||
<p class="text-sm text-gray-900 dark:text-white" x-text="comment.comment"></p>
|
||||
|
||||
Reference in New Issue
Block a user