474 lines
18 KiB
PHP
474 lines
18 KiB
PHP
<?php
|
|
|
|
namespace Modules\Admin\app\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\User;
|
|
use App\Services\JiraService;
|
|
use App\Traits\AnalyzeData;
|
|
use App\Traits\HasFilterRequest;
|
|
use App\Traits\HasOrderByRequest;
|
|
use App\Traits\HasSearchRequest;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Modules\Admin\app\Models\Admin;
|
|
use Modules\Admin\app\Models\Sprint;
|
|
use Modules\Admin\app\Models\UserCriteria;
|
|
use App\Models\Files;
|
|
use App\DataTransferObjects\FileData;
|
|
|
|
class ProfileController extends Controller
|
|
{
|
|
use HasOrderByRequest;
|
|
use HasFilterRequest;
|
|
use HasSearchRequest;
|
|
use AnalyzeData;
|
|
|
|
protected $jiraService;
|
|
|
|
public function __construct(JiraService $jiraService)
|
|
{
|
|
$this->jiraService = $jiraService;
|
|
}
|
|
|
|
|
|
public function getProfilesData(Request $request)
|
|
{
|
|
$user = auth('admins')->user();
|
|
|
|
$userEmail = $user->email;
|
|
$projects = $this->jiraService->getAllProjects();
|
|
|
|
$startDate = $request->input('fromDate');
|
|
$endDate = $request->input('toDate');
|
|
|
|
$userCriterias = UserCriteria::with([
|
|
'sprint' => function ($query) use ($startDate, $endDate) {
|
|
if ($startDate && $endDate) {
|
|
$query->whereBetween('complete_date', [$startDate, $endDate]);
|
|
} elseif ($startDate) {
|
|
$query->where('complete_date', '>=', $startDate);
|
|
} elseif ($endDate) {
|
|
$query->where('complete_date', '<=', $endDate);
|
|
}
|
|
},
|
|
'criteria',
|
|
])->where('user_email', $userEmail)
|
|
->whereHas('sprint', function ($query) use ($startDate, $endDate) {
|
|
if ($startDate && $endDate) {
|
|
$query->whereBetween('complete_date', [$startDate, $endDate]);
|
|
} elseif ($startDate) {
|
|
$query->where('complete_date', '>=', $startDate);
|
|
} elseif ($endDate) {
|
|
$query->where('complete_date', '<=', $endDate);
|
|
}
|
|
})
|
|
->get();
|
|
// dd($userCriterias);
|
|
// Xử lý dữ liệu thành cấu trúc mong muốn
|
|
$projectsData = $userCriterias->groupBy('sprint.project_id')->map(function ($userCriteriasByProject, $projectId) use ($projects) {
|
|
$result = self::getProjectById($projects, $projectId);
|
|
return [
|
|
'name' => $result['name'],
|
|
'sprints' => $userCriteriasByProject->groupBy('sprint.id')->map(function ($userCriteriasBySprint) {
|
|
$sprint = $userCriteriasBySprint->first()->sprint;
|
|
return [
|
|
'name' => $sprint->name,
|
|
'complete_date' => $sprint->complete_date ?? '',
|
|
'criterias' => $userCriteriasBySprint->map(function ($userCriteria) {
|
|
$criteria = $userCriteria->criteria;
|
|
return [
|
|
'criteria' => $criteria->name,
|
|
'note' => $userCriteria->note ?? '',
|
|
'createdBy' => $userCriteria->created_by ?? '', // Lấy tên user từ auth
|
|
'point' => $userCriteria->point ?? '',
|
|
];
|
|
})
|
|
];
|
|
})->values()
|
|
];
|
|
})->values();
|
|
|
|
// Trả về kết quả
|
|
return AbstractController::ResultSuccess($projectsData);
|
|
}
|
|
|
|
public function getProjectById($projects, $inputId)
|
|
{
|
|
$filteredProjects = array_filter($projects, function ($project) use ($inputId) {
|
|
return $project['id'] == $inputId;
|
|
});
|
|
return array_values($filteredProjects) ? array_values($filteredProjects)[0] : array_values($filteredProjects);
|
|
}
|
|
|
|
public function updateProfilesData(Request $request)
|
|
{
|
|
$userInfo = auth('admins')->user();
|
|
$request->validate([
|
|
'file' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048', // Chỉ chấp nhận file ảnh dưới 2MB
|
|
]);
|
|
|
|
$user = User::findOrFail($userInfo->id);
|
|
|
|
if ($user->avatar) {
|
|
Storage::disk('public')->delete($user->avatar);
|
|
}
|
|
|
|
$path = $request->file('file')->store('avatars', 'public');
|
|
$user->avatar = $path;
|
|
$user->save();
|
|
return AbstractController::ResultSuccess($path);
|
|
}
|
|
|
|
public function listFiles(Request $request)
|
|
{
|
|
// Get the root folder from the input URL
|
|
$rootFolder = $request->input('root_folder');
|
|
|
|
// Ensure the root folder is correctly formatted
|
|
$rootFolder = rtrim($rootFolder, '/') . '/';
|
|
|
|
// Get all files and directories in the specified root folder
|
|
$fileList = $this->getDirectoryTree(public_path($rootFolder), env('APP_ENV') === 'local' ? $rootFolder : 'image' . $rootFolder);
|
|
|
|
return response()->json(['data' => $fileList, 'status' => true]);
|
|
}
|
|
|
|
private function getDirectoryTree($dir, $urlRoot)
|
|
{
|
|
$results = [];
|
|
|
|
// Scan the directory for files and folders
|
|
$files = scandir($dir);
|
|
|
|
foreach ($files as $file) {
|
|
if ($file !== '.' && $file !== '..') {
|
|
$filePath = $dir . DIRECTORY_SEPARATOR . $file;
|
|
$fileUrl = url($urlRoot . $file);
|
|
|
|
if (is_dir($filePath)) {
|
|
// If it's a directory, recurse into it
|
|
$results[] = [
|
|
'label' => $file,
|
|
'type' => 'directory',
|
|
'value' => $fileUrl,
|
|
'children' => $this->getDirectoryTree($filePath, $urlRoot . $file . '/')
|
|
];
|
|
} else {
|
|
// If it's a file, add it to the list
|
|
$results[] = [
|
|
'label' => $file,
|
|
'type' => 'file',
|
|
'value' => $fileUrl
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
public function updateProfile(Request $request)
|
|
{
|
|
$name = $request->input('name') ?? auth('admins')->user()->name;
|
|
// Validate the incoming files
|
|
$request->validate([
|
|
'files.*' => 'required|file|mimes:jpg,png,jpeg,pdf,doc,docx,xlsx,xls,csv|max:5120', // Adjust file types and size limit as needed
|
|
]);
|
|
|
|
$uploadedFiles = [];
|
|
$baseDirectory = 'profiles/' . $name;
|
|
$othersDirectory = $baseDirectory . '/others';
|
|
|
|
// Check if the base directory exists, if not create it
|
|
if (!Storage::disk('public')->exists($baseDirectory)) {
|
|
Storage::disk('public')->makeDirectory($baseDirectory);
|
|
}
|
|
|
|
// Check if the "others" directory exists, if not create it
|
|
if (!Storage::disk('public')->exists($othersDirectory)) {
|
|
Storage::disk('public')->makeDirectory($othersDirectory);
|
|
}
|
|
|
|
$adminEmails = Admin::where('permission', 'like', '%admin%')->pluck('email')->toArray();
|
|
$currentUser = auth('admins')->user();
|
|
|
|
if ($request->hasFile('files')) {
|
|
foreach ($request->file('files') as $file) {
|
|
// Store the file and get its path
|
|
$originalFilename = $file->getClientOriginalName();
|
|
if (strpos($originalFilename, '__') === 0) {
|
|
// Store the file in the "others" directory
|
|
$path = $file->storeAs($othersDirectory, $originalFilename, 'public');
|
|
} else {
|
|
// Store the file in the base directory
|
|
$path = $file->storeAs($baseDirectory, $originalFilename, 'public');
|
|
}
|
|
$uploadedFiles[] = $path;
|
|
|
|
// Tạo URL đầy đủ cho file
|
|
$fileUrl = (env('APP_ENV') === 'prod' || env('APP_ENV') === 'production')
|
|
? env('APP_URL') . '/image/' . str_replace('/storage/', '', Storage::url($path))
|
|
: env('APP_URL') . str_replace('/storage/', '', Storage::url($path));
|
|
|
|
// // Gửi email thông báo cho admin
|
|
// foreach ($adminEmails as $adminEmail) {
|
|
// $admin = Admin::where('email', $adminEmail)->first();
|
|
// if ($admin) {
|
|
// $this->sendFileUploadNotification(
|
|
// $admin,
|
|
// "File {$originalFilename} đã được tải lên bởi {$currentUser->name}",
|
|
// $fileUrl,
|
|
// "[APAC Tech] {$currentUser->name} - Đã tải lên file mới"
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
// // Gửi email xác nhận cho người tải lên
|
|
// $this->sendFileUploadNotification(
|
|
// $currentUser,
|
|
// "Bạn đã tải lên file {$originalFilename} thành công",
|
|
// $fileUrl,
|
|
// "[APAC Tech] {$currentUser->name} - Tải file thành công"
|
|
// );
|
|
}
|
|
}
|
|
|
|
return response()->json([
|
|
'status' => true,
|
|
'message' => 'Files uploaded successfully',
|
|
'files' => $uploadedFiles,
|
|
]);
|
|
}
|
|
|
|
public function removeFile(Request $request)
|
|
{
|
|
// Validate that the file URL is provided in the request
|
|
$request->validate([
|
|
'file_url' => 'required|string',
|
|
]);
|
|
|
|
// Get the full file URL from the request
|
|
$fileUrl = $request->input('file_url');
|
|
|
|
// Parse the file path from the URL (remove the base URL part)
|
|
$storagePath = parse_url($fileUrl, PHP_URL_PATH); // Extract the path part of the URL
|
|
$filePath = str_replace(env('APP_ENV') === 'local' ? '/storage/' : '/image/storage/', '', $storagePath); // Remove "/storage/" to get the actual file path
|
|
|
|
// Check if the file exists before attempting to delete it
|
|
if (Storage::disk('public')->exists($filePath)) {
|
|
// Delete the file
|
|
Storage::disk('public')->delete($filePath);
|
|
|
|
return response()->json([
|
|
'status' => true,
|
|
'message' => 'File deleted successfully',
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'status' => false,
|
|
'message' => 'File not found',
|
|
], 404);
|
|
}
|
|
|
|
public function sendFileUploadNotification($user, $description, $url, $subject, $note)
|
|
{
|
|
try {
|
|
// Gửi email bất đồng bộ không cần job
|
|
dispatch(function() use ($user, $description, $url, $subject, $note) {
|
|
Mail::send('emails.file_upload_notification', [
|
|
'user' => $user,
|
|
'description' => $description,
|
|
'url' => $url,
|
|
'note' => $note
|
|
], function ($message) use ($user, $subject) {
|
|
$message->to($user->email)
|
|
->subject($subject);
|
|
});
|
|
})->afterResponse();
|
|
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
Log::error('Error dispatching file upload notification email: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function uploadFiles(Request $request)
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'file' => 'required|file|mimes:jpg,jpeg,png,pdf,doc,docx,xls,xlsx,csv|max:5120',
|
|
'name' => 'required|string|max:255',
|
|
'description' => 'nullable|string',
|
|
'user_name' => 'required|string|max:255'
|
|
]);
|
|
|
|
$file = $request->file('file');
|
|
$user = auth('admins')->user();
|
|
|
|
// Tạo thư mục cho user nếu chưa tồn tại
|
|
$userFolder = 'files/' . $request->user_name;
|
|
if (!Storage::disk('public')->exists($userFolder)) {
|
|
Storage::disk('public')->makeDirectory($userFolder);
|
|
}
|
|
|
|
$path = $file->store($userFolder, 'public');
|
|
|
|
$fileRecord = Files::create([
|
|
'name' => $request->name,
|
|
'url' => $path,
|
|
'type' => $this->getFileType($file->getClientOriginalName()),
|
|
'description' => $request->description,
|
|
'user_id' => Admin::where('name', $request->user_name)->first()->id
|
|
]);
|
|
|
|
$currentUser = Admin::where('name', $request->user_name)->first();
|
|
// Gửi email thông báo cho người upload
|
|
$fileUrl = (env('APP_ENV') === 'prod' || env('APP_ENV') === 'production')
|
|
? env('APP_URL') . '/image' . Storage::url($path)
|
|
: env('APP_URL') . Storage::url($path);
|
|
$this->sendFileUploadNotification(
|
|
$user,
|
|
'Bạn đã tải lên file "' . $request->name . '" thành công',
|
|
$fileUrl,
|
|
"[APAC Tech] {$currentUser->name} - Đã tải lên file mới",
|
|
$request->description ?? 'No description'
|
|
);
|
|
|
|
// Gửi email thông báo cho tất cả admin khác
|
|
$otherAdmins = Admin::where('permission', 'like', '%admin%')->get();
|
|
foreach ($otherAdmins as $admin) {
|
|
$this->sendFileUploadNotification(
|
|
$admin,
|
|
'File "' . $request->name . '" đã được tải lên bởi ' . $user->name,
|
|
$fileUrl,
|
|
"[APAC Tech] {$currentUser->name} - Đã tải lên file mới",
|
|
$request->description ?? 'No description'
|
|
);
|
|
}
|
|
|
|
return response()->json([
|
|
'status' => true,
|
|
'message' => 'File uploaded successfully',
|
|
'data' => [
|
|
'id' => $fileRecord->id,
|
|
'name' => $fileRecord->name,
|
|
'url' => Storage::url($path),
|
|
'type' => $fileRecord->type,
|
|
'description' => $fileRecord->description
|
|
]
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'status' => false,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function getFiles()
|
|
{
|
|
try {
|
|
// Lấy tất cả users
|
|
$users = Admin::all();
|
|
|
|
// Lấy files và map theo cấu trúc
|
|
$files = Files::with('user')->get()
|
|
->map(function($file) {
|
|
return [
|
|
'id' => $file->id,
|
|
'name' => $file->name,
|
|
'url' => Storage::url($file->url),
|
|
'type' => $file->type,
|
|
'description' => $file->description,
|
|
'created_at' => $file->created_at,
|
|
'user_id' => $file->user_id,
|
|
'user_name' => $file->user->name
|
|
];
|
|
});
|
|
|
|
// Tạo mảng kết quả với tất cả users, không có file thì mảng rỗng
|
|
$result = $users->pluck('name')->mapWithKeys(function($userName) use ($files) {
|
|
$userFiles = $files->where('user_name', $userName)
|
|
->map(function($file) {
|
|
return (object)[
|
|
'id' => $file['id'],
|
|
'name' => $file['name'],
|
|
'url' => $file['url'],
|
|
'type' => $file['type'],
|
|
'description' => $file['description'],
|
|
'created_at' => $file['created_at'],
|
|
'user_id' => $file['user_id']
|
|
];
|
|
})->values();
|
|
|
|
return [$userName => $userFiles];
|
|
});
|
|
|
|
return response()->json([
|
|
'status' => true,
|
|
'data' => $result
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'status' => false,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function deleteFile($id)
|
|
{
|
|
try {
|
|
$file = Files::findOrFail($id);
|
|
$user = auth('admins')->user();
|
|
|
|
if ($file->user_id !== $user->id) {
|
|
return response()->json([
|
|
'status' => false,
|
|
'message' => 'Unauthorized'
|
|
], 403);
|
|
}
|
|
|
|
Storage::disk('public')->delete($file->url);
|
|
$file->delete();
|
|
|
|
return response()->json([
|
|
'status' => true,
|
|
'message' => 'File deleted successfully'
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'status' => false,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
private function getFileType($filename)
|
|
{
|
|
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
|
|
|
$typeMap = [
|
|
'pdf' => 'document',
|
|
'doc' => 'document',
|
|
'docx' => 'document',
|
|
'jpg' => 'image',
|
|
'jpeg' => 'image',
|
|
'png' => 'image',
|
|
'xls' => 'spreadsheet',
|
|
'xlsx' => 'spreadsheet',
|
|
'csv' => 'spreadsheet'
|
|
];
|
|
|
|
return $typeMap[$extension] ?? 'other';
|
|
}
|
|
}
|