WIP: Road to 1.0.0 #1
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Faker\Factory;
|
||||||
|
use Faker\Generator;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class MakeFile extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'files:make {count : How many test files to generate}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Generates test files for the TeamFile model. Use in conjunction with it\'s factory.';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The faker instance used to obtain dummy text.
|
||||||
|
*
|
||||||
|
* @var Generator
|
||||||
|
*/
|
||||||
|
private $faker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->faker = Factory::create();
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$count = $this->argument('count');
|
||||||
|
$this->info('Creating ' . $this->argument('count') . ' files!');
|
||||||
|
|
||||||
|
for ($max = 1; $max < $count; $max++)
|
||||||
|
{
|
||||||
|
Storage::disk('local')->put('factory_files/testfile_' . rand(0, 5000) . '.txt', $this->faker->paragraphs(40, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Finished creating files! They will be randomly picked by the factory.');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\TeamFile;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use League\Flysystem\FileNotFoundException;
|
||||||
|
|
||||||
|
class TeamFileController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
if (is_null(Auth::user()->currentTeam))
|
||||||
|
{
|
||||||
|
$request->session()->flash('error', 'Please choose a team before viewing it\'s files.');
|
||||||
|
return redirect()->to(route('teams.index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('dashboard.teams.team-files')
|
||||||
|
->with('files', TeamFile::with('team', 'uploader')->paginate(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function download(Request $request, TeamFile $teamFile)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Storage::download('uploads/' . $teamFile->name);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException $ex)
|
||||||
|
{
|
||||||
|
$request->session()->flash('error', 'Sorry, but the requested file could not be found in storage. Sometimes, files may be physically deleted by admins, but not from the app\'s database.');
|
||||||
|
return redirect()->back();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param \App\TeamFile $teamFile
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(TeamFile $teamFile)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param \App\TeamFile $teamFile
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit(TeamFile $teamFile)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \App\TeamFile $teamFile
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(Request $request, TeamFile $teamFile)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \App\TeamFile $teamFile
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(TeamFile $teamFile)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,4 +36,10 @@ class Team extends TeamworkTeam
|
||||||
{
|
{
|
||||||
return $this->belongsToMany('App\Vacancy', 'team_has_vacancy');
|
return $this->belongsToMany('App\Vacancy', 'team_has_vacancy');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function files()
|
||||||
|
{
|
||||||
|
return $this->hasMany('App\TeamFile', 'team_id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Mpociot\Teamwork\Traits\UsedByTeams;
|
||||||
|
|
||||||
|
class TeamFile extends Model
|
||||||
|
{
|
||||||
|
use HasFactory, UsedByTeams;
|
||||||
|
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'uploaded_by',
|
||||||
|
'team_id',
|
||||||
|
'name',
|
||||||
|
'fs_location',
|
||||||
|
'extension'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function uploader()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\User', 'uploaded_by', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function team()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Team');
|
||||||
|
}
|
||||||
|
}
|
10
app/User.php
10
app/User.php
|
@ -60,7 +60,8 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
//
|
// RELATIONSHIPS
|
||||||
|
|
||||||
public function applications()
|
public function applications()
|
||||||
{
|
{
|
||||||
return $this->hasMany('App\Application', 'applicantUserID', 'id');
|
return $this->hasMany('App\Application', 'applicantUserID', 'id');
|
||||||
|
@ -86,6 +87,13 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||||
return $this->hasMany('App\Comment', 'authorID', 'id');
|
return $this->hasMany('App\Comment', 'authorID', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function files()
|
||||||
|
{
|
||||||
|
return $this->hasMany('App\TeamFile', 'uploaded_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTILITY LOGIC
|
||||||
|
|
||||||
public function isBanned()
|
public function isBanned()
|
||||||
{
|
{
|
||||||
return ! $this->bans()->get()->isEmpty();
|
return ! $this->bans()->get()->isEmpty();
|
||||||
|
|
|
@ -607,6 +607,8 @@ return [
|
||||||
'location' => 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css',
|
'location' => 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => 'DropzoneJS',
|
'name' => 'DropzoneJS',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
|
@ -624,5 +626,4 @@ return [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\TeamFile;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class TeamFileFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name of the factory's corresponding model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $model = TeamFile::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function definition()
|
||||||
|
{
|
||||||
|
$prefix = Storage::disk('local')->getAdapter()->getPathPrefix();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'uploaded_by' => rand(1, 10), // Also assuming that the user seeder has ran before
|
||||||
|
'team_id' => rand(1, 3), // Assuming you create 3 teams beforehand
|
||||||
|
'name' => $this->faker->file($prefix . 'factory_files', $prefix . 'uploads', false),
|
||||||
|
'caption' => $this->faker->sentence(),
|
||||||
|
'description' => $this->faker->paragraphs(3, true),
|
||||||
|
'fs_location' => $this->faker->file($prefix . 'factory_files', $prefix . 'uploads'),
|
||||||
|
'extension' => 'txt',
|
||||||
|
'size' => rand(1, 1000) // random fake size between 0 bytes and 1 mb
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateTeamFilesTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('team_files', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->bigInteger('uploaded_by')->unsigned()->index();
|
||||||
|
$table->integer('team_id')->unsigned()->index();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('fs_location'); // filesystem location
|
||||||
|
$table->string('extension');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->foreign('uploaded_by')
|
||||||
|
->references('id')
|
||||||
|
->on('users')
|
||||||
|
->cascadeOnDelete()
|
||||||
|
->cascadeOnUpdate();
|
||||||
|
|
||||||
|
$table->foreign('team_id')
|
||||||
|
->references('id')
|
||||||
|
->on('teams')
|
||||||
|
->cascadeOnDelete()
|
||||||
|
->cascadeOnUpdate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('team_files');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddDetailsToTeamFiles extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('team_files', function (Blueprint $table) {
|
||||||
|
$table->integer('size')->nullable()->after('extension');
|
||||||
|
$table->string('caption')->nullable()->after('name');
|
||||||
|
$table->mediumText('description')->nullable()->after('caption');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('team_files', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('size');
|
||||||
|
$table->dropColumn('caption');
|
||||||
|
$table->dropColumn('description');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,5 +35,8 @@ class DatabaseSeeder extends Seeder
|
||||||
$this->call(PermissionSeeder::class);
|
$this->call(PermissionSeeder::class);
|
||||||
$this->call(UserSeeder::class);
|
$this->call(UserSeeder::class);
|
||||||
$this->call(DefaultOptionsSeeder::class);
|
$this->call(DefaultOptionsSeeder::class);
|
||||||
|
$this->call(NewPermissions::class);
|
||||||
|
$this->call(TeamSeeder::class);
|
||||||
|
$this->call(TeamFileSeeder::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\TeamFile;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class TeamFileSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
TeamFile::factory()->count(50)->create();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
|
@ -0,0 +1,113 @@
|
||||||
|
@extends('adminlte::page')
|
||||||
|
|
||||||
|
@section('title', config('app.name') . ' | Team Files')
|
||||||
|
|
||||||
|
@section('content_header')
|
||||||
|
<h1>{{config('app.name')}} / Teams / Files</h1>
|
||||||
|
@stop
|
||||||
|
|
||||||
|
@section('js')
|
||||||
|
|
||||||
|
<x-global-errors></x-global-errors>
|
||||||
|
@stop
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<x-modal id="upload-dropzone" modal-label="upload-dropzone-modal" modal-title="Upload Files" include-close-button="true">
|
||||||
|
|
||||||
|
<form class="dropzone" id="teamFile" action="{{route('uploadTeamFile')}}"></form>
|
||||||
|
|
||||||
|
<x-slot name="modalFooter">
|
||||||
|
|
||||||
|
</x-slot>
|
||||||
|
</x-modal>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-3 offset-3">
|
||||||
|
<img src="/img/files.svg" width="230px" height="230px" alt="Team files illustration">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
|
<div class="card bg-gray-dark">
|
||||||
|
|
||||||
|
<div class="card-header bg-indigo">
|
||||||
|
<div class="card-title"><h4 class="text-bold">Team Files <span class="badge badge-warning"><i class="fas fa-check-circle"></i> {{ (Auth::user()->currentTeam) ? Auth::user()->currentTeam->name : '(No team)' }}</span></h4></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
@if(!$files->isEmpty())
|
||||||
|
|
||||||
|
<table class="table table-active table-borderless" style="white-space: nowrap">
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>File name</th>
|
||||||
|
<th>Caption</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th>Last updated</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
@foreach($files as $file)
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>{{$file->id}}</td>
|
||||||
|
<td>{{ Str::of($file->name)->limit(10, '(..).' . $file->extension) }}</td>
|
||||||
|
<td>{{ Str::of($file->caption)->limit(10) }}</td>
|
||||||
|
<td>{{ $file->size }} bytes</td>
|
||||||
|
<td>{{ $file->updated_at }}</td>
|
||||||
|
<td>
|
||||||
|
<button rel="buttonTxtTooltip" data-toggle="tooltip" data-placement="top" title="Download" type="button" class="btn btn-success btn-sm ml-3" onclick="window.location='{{route('downloadTeamFile', ['teamFile' => $file->id])}}'"><i class="fas fa-download"></i></button>
|
||||||
|
<button rel="buttonTxtTooltip" data-toggle="tooltip" data-placement="top" title="View" type="button" class="btn btn-success btn-sm ml-3"><i class="fas fa-eye"></i></button>
|
||||||
|
<button rel="buttonTxtTooltip" data-toggle="tooltip" data-placement="top" title="Delete File" type="button" class="btn btn-danger btn-sm ml-3"><i class="fas fa-trash"></i></button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@else
|
||||||
|
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
|
||||||
|
<span class="text-bold"><i class="fas fa-exclamation-triangle"></i> There are currently no team files. Try uploading some to get started.</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-footer text-center">
|
||||||
|
<button type="button" class="btn btn-warning" onclick="$('#upload-dropzone').modal('show')"><i class="fas fa-upload"></i> Upload Files</button>
|
||||||
|
{{ $files->links() }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@stop
|
||||||
|
|
||||||
|
@section('footer')
|
||||||
|
@include('breadcrumbs.dashboard.footer')
|
||||||
|
@stop
|
|
@ -31,6 +31,7 @@ use App\Http\Controllers\FormController;
|
||||||
use App\Http\Controllers\HomeController;
|
use App\Http\Controllers\HomeController;
|
||||||
use App\Http\Controllers\ProfileController;
|
use App\Http\Controllers\ProfileController;
|
||||||
use App\Http\Controllers\TeamController;
|
use App\Http\Controllers\TeamController;
|
||||||
|
use App\Http\Controllers\TeamFileController;
|
||||||
use App\Http\Controllers\UserController;
|
use App\Http\Controllers\UserController;
|
||||||
use App\Http\Controllers\VacancyController;
|
use App\Http\Controllers\VacancyController;
|
||||||
use App\Http\Controllers\VoteController;
|
use App\Http\Controllers\VoteController;
|
||||||
|
@ -86,6 +87,17 @@ Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => ['lo
|
||||||
Route::get('teams/invites/{action}/{token}', [TeamController::class, 'processInviteAction'])
|
Route::get('teams/invites/{action}/{token}', [TeamController::class, 'processInviteAction'])
|
||||||
->name('processInvite');
|
->name('processInvite');
|
||||||
|
|
||||||
|
|
||||||
|
Route::get('team/files', [TeamFileController::class, 'index'])
|
||||||
|
->name('showTeamFiles');
|
||||||
|
|
||||||
|
Route::post('team/files/upload', [TeamFileController::class, 'store'])
|
||||||
|
->name('uploadTeamFile');
|
||||||
|
|
||||||
|
Route::get('team/files/{teamFile}/download', [TeamFileController::class, 'download'])
|
||||||
|
->name('downloadTeamFile');
|
||||||
|
|
||||||
|
|
||||||
Route::group(['prefix' => '/applications'], function () {
|
Route::group(['prefix' => '/applications'], function () {
|
||||||
Route::get('/my-applications', [ApplicationController::class, 'showUserApps'])
|
Route::get('/my-applications', [ApplicationController::class, 'showUserApps'])
|
||||||
->name('showUserApps')
|
->name('showUserApps')
|
||||||
|
|
Loading…
Reference in New Issue