mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-05 18:23:48 +00:00
UI enhancements for file request
This commit is contained in:
@@ -24,10 +24,11 @@ class UploadRequestFactory extends Factory
|
|||||||
return [
|
return [
|
||||||
'id' => $this->faker->uuid,
|
'id' => $this->faker->uuid,
|
||||||
'user_id' => $this->faker->uuid,
|
'user_id' => $this->faker->uuid,
|
||||||
'folder_id' => $this->faker->uuid,
|
'folder_id' => $this->faker->uuid,
|
||||||
'email' => $this->faker->email,
|
'email' => $this->faker->email,
|
||||||
'notes' => $this->faker->realText(80),
|
'name' => $this->faker->name,
|
||||||
'status' => $this->faker->randomElement(
|
'notes' => $this->faker->realText(80),
|
||||||
|
'status' => $this->faker->randomElement(
|
||||||
['active', 'filled', 'expired']
|
['active', 'filled', 'expired']
|
||||||
),
|
),
|
||||||
'created_at' => $this->faker->dateTimeBetween('-1 months'),
|
'created_at' => $this->faker->dateTimeBetween('-1 months'),
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ class CreateUploadRequestsTable extends Migration
|
|||||||
Schema::create('upload_requests', function (Blueprint $table) {
|
Schema::create('upload_requests', function (Blueprint $table) {
|
||||||
$table->uuid('id');
|
$table->uuid('id');
|
||||||
$table->uuid('user_id');
|
$table->uuid('user_id');
|
||||||
$table->uuid('folder_id');
|
$table->uuid('folder_id')->nullable();
|
||||||
$table->enum('status', ['active', 'filling', 'filled', 'expired'])->default('active');
|
$table->enum('status', ['active', 'filling', 'filled', 'expired'])->default('active');
|
||||||
$table->string('email')->nullable();
|
$table->string('email')->nullable();
|
||||||
|
$table->text('name')->nullable();
|
||||||
$table->longText('notes')->nullable();
|
$table->longText('notes')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
$table->charset = 'utf8mb4';
|
$table->charset = 'utf8mb4';
|
||||||
|
|||||||
@@ -16,11 +16,12 @@
|
|||||||
v-slot="{ invalid }"
|
v-slot="{ invalid }"
|
||||||
tag="form"
|
tag="form"
|
||||||
>
|
>
|
||||||
|
<!--Send Request by Email-->
|
||||||
<AppInputSwitch
|
<AppInputSwitch
|
||||||
:title="$t('Send Request by Email')"
|
:title="$t('Send Request by Email')"
|
||||||
:description="$t('Send your file request on recipients email')"
|
:description="$t('Send your file request on recipients email')"
|
||||||
>
|
>
|
||||||
<SwitchInput v-model="shareViaEmail" :state="shareViaEmail" class="switch" />
|
<SwitchInput v-model="shareViaEmail" :state="shareViaEmail" />
|
||||||
</AppInputSwitch>
|
</AppInputSwitch>
|
||||||
|
|
||||||
<!--Set email-->
|
<!--Set email-->
|
||||||
@@ -44,6 +45,35 @@
|
|||||||
</AppInputText>
|
</AppInputText>
|
||||||
</ValidationProvider>
|
</ValidationProvider>
|
||||||
|
|
||||||
|
<!--Custom Folder Name-->
|
||||||
|
<AppInputSwitch
|
||||||
|
:title="$t('Custom Folder Name')"
|
||||||
|
:description="$t('Created folder with files will be named with your own name.')"
|
||||||
|
>
|
||||||
|
<SwitchInput v-model="customFolderName" :state="customFolderName" />
|
||||||
|
</AppInputSwitch>
|
||||||
|
|
||||||
|
<!--Set email-->
|
||||||
|
<ValidationProvider
|
||||||
|
v-if="customFolderName"
|
||||||
|
tag="div"
|
||||||
|
mode="passive"
|
||||||
|
name="Name"
|
||||||
|
rules="required"
|
||||||
|
v-slot="{ errors }"
|
||||||
|
>
|
||||||
|
<AppInputText :error="errors[0]" class="-mt-2">
|
||||||
|
<input
|
||||||
|
v-model="form.name"
|
||||||
|
:class="{ 'border-red': errors[0] }"
|
||||||
|
type="text"
|
||||||
|
ref="input"
|
||||||
|
class="focus-border-theme input-dark"
|
||||||
|
:placeholder="$t('Type name...')"
|
||||||
|
/>
|
||||||
|
</AppInputText>
|
||||||
|
</ValidationProvider>
|
||||||
|
|
||||||
<!--Set note-->
|
<!--Set note-->
|
||||||
<ValidationProvider tag="div" mode="passive" name="Note" v-slot="{ errors }">
|
<ValidationProvider tag="div" mode="passive" name="Note" v-slot="{ errors }">
|
||||||
<AppInputText :title="$t('Message (optional)')" :description="$t('This message will be showed for your email recipient or in the upload page.')" :error="errors[0]" :is-last="true">
|
<AppInputText :title="$t('Message (optional)')" :description="$t('This message will be showed for your email recipient or in the upload page.')" :error="errors[0]" :is-last="true">
|
||||||
@@ -124,9 +154,11 @@ export default {
|
|||||||
email: undefined,
|
email: undefined,
|
||||||
notes: undefined,
|
notes: undefined,
|
||||||
folder_id: undefined,
|
folder_id: undefined,
|
||||||
|
name: undefined,
|
||||||
},
|
},
|
||||||
generatedUploadRequest: undefined,
|
generatedUploadRequest: undefined,
|
||||||
shareViaEmail: false,
|
shareViaEmail: false,
|
||||||
|
customFolderName: false,
|
||||||
pickedItem: undefined,
|
pickedItem: undefined,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}
|
}
|
||||||
@@ -159,8 +191,10 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
events.$on('popup:open', (args) => {
|
events.$on('popup:open', (args) => {
|
||||||
if (args.name === 'create-file-request') this.pickedItem = args.item
|
if (args.name === 'create-file-request')
|
||||||
this.form.folder_id = args.item.data.id
|
this.pickedItem = args.item
|
||||||
|
|
||||||
|
this.form.folder_id = args.item?.data.id
|
||||||
})
|
})
|
||||||
|
|
||||||
// Close popup
|
// Close popup
|
||||||
@@ -172,8 +206,10 @@ export default {
|
|||||||
this.pickedItem = undefined
|
this.pickedItem = undefined
|
||||||
|
|
||||||
this.shareViaEmail = false
|
this.shareViaEmail = false
|
||||||
|
this.customFolderName = false
|
||||||
|
|
||||||
this.form = {
|
this.form = {
|
||||||
|
name: undefined,
|
||||||
email: undefined,
|
email: undefined,
|
||||||
notes: undefined,
|
notes: undefined,
|
||||||
folder_id: undefined,
|
folder_id: undefined,
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ import ThumbnailItem from './ThumbnailItem'
|
|||||||
import ButtonBase from '../FilesView/ButtonBase'
|
import ButtonBase from '../FilesView/ButtonBase'
|
||||||
import Spinner from '../FilesView/Spinner'
|
import Spinner from '../FilesView/Spinner'
|
||||||
import TreeMenu from './TreeMenu'
|
import TreeMenu from './TreeMenu'
|
||||||
import { isArray, isNull } from 'lodash'
|
import { isArray } from 'lodash'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { events } from '../../bus'
|
import { events } from '../../bus'
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<PopupWrapper>
|
<PopupWrapper>
|
||||||
<div class="flex h-full -translate-y-7 transform items-center justify-center px-8 text-center md:translate-y-0">
|
<div class="flex h-full -translate-y-7 transform items-center justify-center px-8 text-center md:translate-y-0">
|
||||||
<div>
|
<div>
|
||||||
<img src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f914.svg" alt="" class="mx-auto mb-4 w-20 md:mt-6" />
|
<img src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f914.svg" alt="" class="mx-auto mb-4 w-20 md:mt-6 min-h-[80px]" />
|
||||||
|
|
||||||
<h1 v-if="title" class="mb-2 text-2xl font-bold">
|
<h1 v-if="title" class="mb-2 text-2xl font-bold">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<!--Item icon-->
|
<!--Item icon-->
|
||||||
<hard-drive-icon
|
<hard-drive-icon
|
||||||
v-if="['public', 'files'].includes(nodes.location)"
|
v-if="['public', 'files', 'upload-request'].includes(nodes.location)"
|
||||||
size="17"
|
size="17"
|
||||||
class="icon vue-feather shrink-0"
|
class="icon vue-feather shrink-0"
|
||||||
:class="{ 'text-theme dark-text-theme': isSelectedItem }"
|
:class="{ 'text-theme dark-text-theme': isSelectedItem }"
|
||||||
|
|||||||
@@ -4,7 +4,11 @@
|
|||||||
<FilePreview />
|
<FilePreview />
|
||||||
<Spotlight />
|
<Spotlight />
|
||||||
|
|
||||||
<!--Mobile Navigation-->
|
<!--Spotlight Addons-->
|
||||||
|
<CreateUploadRequestPopup />
|
||||||
|
<CreateTeamFolderPopup />
|
||||||
|
|
||||||
|
<!--Mobile Navigation-->
|
||||||
<MobileNavigation />
|
<MobileNavigation />
|
||||||
|
|
||||||
<!--ConfirmPopup Popup-->
|
<!--ConfirmPopup Popup-->
|
||||||
@@ -82,6 +86,8 @@ import {
|
|||||||
UsersIcon,
|
UsersIcon,
|
||||||
} from 'vue-feather-icons'
|
} from 'vue-feather-icons'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import CreateUploadRequestPopup from "../components/Others/CreateUploadRequestPopup";
|
||||||
|
import CreateTeamFolderPopup from "../components/Teams/CreateTeamFolderPopup";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Admin',
|
name: 'Admin',
|
||||||
@@ -186,6 +192,8 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
CreateTeamFolderPopup,
|
||||||
|
CreateUploadRequestPopup,
|
||||||
MobileNavigationToolbar,
|
MobileNavigationToolbar,
|
||||||
FilePreview,
|
FilePreview,
|
||||||
Spotlight,
|
Spotlight,
|
||||||
|
|||||||
@@ -142,7 +142,7 @@
|
|||||||
{{ emptyPageDescription }}
|
{{ emptyPageDescription }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<InfoBox class="max-w-[420px] mx-auto">
|
<InfoBox v-if="uploadRequest.data.attributes.notes && uploadRequest.data.attributes.status === 'active'" class="max-w-[420px] mx-auto">
|
||||||
<b>{{ $t('{name} leave you a message', {name: userName}) }}: </b>
|
<b>{{ $t('{name} leave you a message', {name: userName}) }}: </b>
|
||||||
<p>{{ uploadRequest.data.attributes.notes }}</p>
|
<p>{{ uploadRequest.data.attributes.notes }}</p>
|
||||||
</InfoBox>
|
</InfoBox>
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
<FilePreview />
|
<FilePreview />
|
||||||
<Spotlight />
|
<Spotlight />
|
||||||
|
|
||||||
|
<!--Spotlight Addons-->
|
||||||
|
<CreateUploadRequestPopup />
|
||||||
|
<CreateTeamFolderPopup />
|
||||||
|
|
||||||
<ConfirmPopup />
|
<ConfirmPopup />
|
||||||
|
|
||||||
<ConfirmPassword />
|
<ConfirmPassword />
|
||||||
@@ -87,10 +91,14 @@ import { mapGetters } from 'vuex'
|
|||||||
import CardNavigation from '../components/Admin/CardNavigation'
|
import CardNavigation from '../components/Admin/CardNavigation'
|
||||||
import ConfirmPassword from '../components/Others/ConfirmPassword'
|
import ConfirmPassword from '../components/Others/ConfirmPassword'
|
||||||
import MobileNavigationToolbar from '../components/Mobile/MobileNavigationToolbar'
|
import MobileNavigationToolbar from '../components/Mobile/MobileNavigationToolbar'
|
||||||
|
import CreateUploadRequestPopup from "../components/Others/CreateUploadRequestPopup";
|
||||||
|
import CreateTeamFolderPopup from "../components/Teams/CreateTeamFolderPopup";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
components: {
|
components: {
|
||||||
|
CreateTeamFolderPopup,
|
||||||
|
CreateUploadRequestPopup,
|
||||||
MobileNavigationToolbar,
|
MobileNavigationToolbar,
|
||||||
MobileNavigation,
|
MobileNavigation,
|
||||||
ConfirmPassword,
|
ConfirmPassword,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Domain\UploadRequest\Controllers;
|
namespace Domain\UploadRequest\Controllers;
|
||||||
|
|
||||||
use Auth;
|
use Auth;
|
||||||
@@ -16,6 +17,7 @@ class CreateUploadRequestController extends Controller
|
|||||||
'folder_id' => $request->input('folder_id'),
|
'folder_id' => $request->input('folder_id'),
|
||||||
'email' => $request->input('email'),
|
'email' => $request->input('email'),
|
||||||
'notes' => $request->input('notes'),
|
'notes' => $request->input('notes'),
|
||||||
|
'name' => $request->input('name'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// If user type email, notify by email
|
// If user type email, notify by email
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ class UploadFilesForUploadRequestController
|
|||||||
// Create folder
|
// Create folder
|
||||||
DB::table('folders')->insert([
|
DB::table('folders')->insert([
|
||||||
'id' => $uploadRequest->id,
|
'id' => $uploadRequest->id,
|
||||||
'parent_id' => $uploadRequest->folder_id,
|
'parent_id' => $uploadRequest->folder_id ?? null,
|
||||||
'user_id' => $uploadRequest->user_id,
|
'user_id' => $uploadRequest->user_id,
|
||||||
'name' => "Upload Request from $timestampName",
|
'name' => $uploadRequest->name ?? "Upload Request from $timestampName",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update upload request status
|
// Update upload request status
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Domain\UploadRequest\Requests;
|
namespace Domain\UploadRequest\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
@@ -23,9 +24,10 @@ class StoreUploadRequest extends FormRequest
|
|||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'email' => 'sometimes|string',
|
'email' => 'sometimes|string|nullable',
|
||||||
'notes' => 'sometimes|string',
|
'notes' => 'sometimes|string|nullable',
|
||||||
'folder_id' => 'required|string',
|
'folder_id' => 'sometimes|string',
|
||||||
|
'name' => 'sometimes|string|nullable',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Domain\UploadRequest;
|
namespace Tests\Domain\UploadRequest;
|
||||||
|
|
||||||
use Domain\UploadRequest\Notifications\UploadRequestFulfilledNotification;
|
use Domain\UploadRequest\Notifications\UploadRequestFulfilledNotification;
|
||||||
@@ -78,6 +79,34 @@ class UploadRequestTest extends TestCase
|
|||||||
Notification::assertNothingSent();
|
Notification::assertNothingSent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function user_create_upload_request_with_name()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->hasSettings()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$this
|
||||||
|
->actingAs($user)
|
||||||
|
->postJson('/api/upload-request', [
|
||||||
|
'folder_id' => '00cacdb9-1d09-4a32-8ad7-c0d45d66b758',
|
||||||
|
'notes' => 'Please send me your files...',
|
||||||
|
'name' => 'My name',
|
||||||
|
])
|
||||||
|
->assertCreated();
|
||||||
|
|
||||||
|
$this->assertDatabasehas('upload_requests', [
|
||||||
|
'folder_id' => '00cacdb9-1d09-4a32-8ad7-c0d45d66b758',
|
||||||
|
'notes' => 'Please send me your files...',
|
||||||
|
'email' => null,
|
||||||
|
'name' => 'My name',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Notification::assertNothingSent();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@@ -103,7 +132,7 @@ class UploadRequestTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function it_upload_file_and_create_upload_request_folder()
|
public function it_upload_file_and_create_upload_request_folder_without_custom_folder_name()
|
||||||
{
|
{
|
||||||
$user = User::factory()
|
$user = User::factory()
|
||||||
->hasSettings()
|
->hasSettings()
|
||||||
@@ -114,6 +143,7 @@ class UploadRequestTest extends TestCase
|
|||||||
'status' => 'active',
|
'status' => 'active',
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
|
'name' => null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$file = UploadedFile::fake()
|
$file = UploadedFile::fake()
|
||||||
@@ -144,6 +174,51 @@ class UploadRequestTest extends TestCase
|
|||||||
Storage::assertExists("files/$user->id/$file->basename");
|
Storage::assertExists("files/$user->id/$file->basename");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_upload_file_and_create_upload_request_folder_with_custom_folder_name()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->hasSettings()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$uploadRequest = UploadRequest::factory()
|
||||||
|
->create([
|
||||||
|
'status' => 'active',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'created_at' => now(),
|
||||||
|
'name' => 'My Documents',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()
|
||||||
|
->create('fake-file.pdf', 12000000, 'application/pdf');
|
||||||
|
|
||||||
|
$this
|
||||||
|
->postJson("/api/upload-request/$uploadRequest->id/upload", [
|
||||||
|
'filename' => $file->name,
|
||||||
|
'file' => $file,
|
||||||
|
'parent_id' => null,
|
||||||
|
'path' => "/$file->name",
|
||||||
|
'is_last' => 'true',
|
||||||
|
])->assertStatus(201);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->assertDatabaseHas('upload_requests', [
|
||||||
|
'status' => 'filling',
|
||||||
|
])
|
||||||
|
->assertDatabaseHas('folders', [
|
||||||
|
'id' => $uploadRequest->id,
|
||||||
|
'name' => 'My Documents',
|
||||||
|
])->assertDatabaseHas('files', [
|
||||||
|
'parent_id' => $uploadRequest->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$file = File::first();
|
||||||
|
|
||||||
|
Storage::assertExists("files/$user->id/$file->basename");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user