create/get upload request backend

This commit is contained in:
Čarodej
2022-02-17 16:55:35 +01:00
parent 45a3b5415b
commit 6db8b0662a
15 changed files with 273 additions and 28 deletions

View File

@@ -1,6 +1,6 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:XP4FSfZLrj3n2MbhbOVWp4ldCbU0Ew+bhiEpHyOpxVw=
APP_KEY=base64:MzktLd8L9CrZsaNj5lDDewmUcI9VVQWq5eWMFxU5LvI=
APP_DEBUG=true
APP_URL=http://localhost
APP_DEMO=false

View File

@@ -18,8 +18,8 @@ class CreateUploadRequestsTable extends Migration
$table->uuid('user_id');
$table->uuid('folder_id');
$table->enum('status', ['active', 'filled', 'expired'])->default('active');
$table->string('email');
$table->longText('notes');
$table->string('email')->nullable();
$table->longText('notes')->nullable();
$table->timestamps();
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';

View File

@@ -0,0 +1,167 @@
<template>
<PopupWrapper name="create-upload-request">
<!--Title-->
<PopupHeader :title="$t('Create Upload Request')" icon="upload" />
<!--Content-->
<PopupContent>
<!--Item Thumbnail-->
<ThumbnailItem class="mb-5" :item="pickedItem" />
<!--Form to set upload request-->
<ValidationObserver
v-if="!generatedUploadRequest"
@submit.prevent="createUploadRequest"
ref="createForm"
v-slot="{ invalid }"
tag="form"
>
<AppInputSwitch
:title="$t('Send Request by Email')"
:description="$t('Send your file request on recipients email')"
>
<SwitchInput v-model="shareViaEmail" :state="shareViaEmail" class="switch" />
</AppInputSwitch>
<!--Set email-->
<ValidationProvider
v-if="shareViaEmail"
tag="div"
mode="passive"
name="Email"
rules="required"
v-slot="{ errors }"
>
<AppInputText :error="errors[0]">
<input
v-model="form.email"
:class="{ 'border-red': errors[0] }"
type="text"
ref="input"
class="focus-border-theme input-dark"
:placeholder="$t('Type email...')"
/>
</AppInputText>
</ValidationProvider>
<!--Set note-->
<ValidationProvider tag="div" mode="passive" name="Note" v-slot="{ errors }">
<AppInputText :title="$t('Message (optional)')" :error="errors[0]" :is-last="true">
<textarea
v-model="form.notes"
rows="2"
:class="{ 'border-red': errors[0] }"
type="text"
ref="input"
class="focus-border-theme input-dark"
:placeholder="$t('Type message for recipient...')"
></textarea>
</AppInputText>
</ValidationProvider>
</ValidationObserver>
<!--Copy generated link-->
<AppInputText v-if="generatedUploadRequest" :title="$t('Copy your upload request link')" :is-last="true">
<CopyInput :str="generatedUploadRequest.data.attributes.url" />
</AppInputText>
</PopupContent>
<!--Actions-->
<PopupActions v-if="!generatedUploadRequest">
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
>{{ $t('popup_move_item.cancel') }}
</ButtonBase>
<ButtonBase class="w-full" @click.native="createUploadRequest" :loading="isLoading" button-style="theme"
>{{ $t('Create Request') }}
</ButtonBase>
</PopupActions>
<!--Actions-->
<PopupActions v-if="generatedUploadRequest">
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="theme"
>{{ $t('shared_form.button_done') }}
</ButtonBase>
</PopupActions>
</PopupWrapper>
</template>
<script>
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
import AppInputSwitch from '../Admin/AppInputSwitch'
import { required } from 'vee-validate/dist/rules'
import ButtonBase from '../FilesView/ButtonBase'
import AppInputText from '../Admin/AppInputText'
import PopupWrapper from './Popup/PopupWrapper'
import PopupActions from './Popup/PopupActions'
import PopupContent from './Popup/PopupContent'
import PopupHeader from './Popup/PopupHeader'
import SwitchInput from './Forms/SwitchInput'
import ThumbnailItem from './ThumbnailItem'
import CopyInput from './Forms/CopyInput'
import { events } from '../../bus'
import axios from 'axios'
export default {
name: 'CreateUploadRequestPopup',
components: {
ValidationProvider,
ValidationObserver,
AppInputSwitch,
ThumbnailItem,
AppInputText,
PopupWrapper,
PopupActions,
PopupContent,
SwitchInput,
PopupHeader,
ButtonBase,
CopyInput,
required,
},
data() {
return {
form: {
email: undefined,
notes: undefined,
folder_id: undefined,
},
generatedUploadRequest: undefined,
shareViaEmail: false,
pickedItem: false,
isLoading: false,
}
},
methods: {
async createUploadRequest() {
// Validate fields
const isValid = await this.$refs.createForm.validate()
if (!isValid) return
this.isLoading = true
// Send request to get share link
axios
.post(`/api/upload-request`, this.form)
.then((response) => {
this.generatedUploadRequest = response.data
})
.catch(() => {
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
})
.finally(() => {
this.isLoading = false
})
},
},
created() {
events.$on('popup:open', (args) => {
if (args.name === 'create-upload-request') this.pickedItem = args.item
this.form.folder_id = args.item.data.id
})
},
}
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div @click="copyUrl" class="relative flex items-center">
<input ref="sel" :value="str" :id="id" type="text" class="focus-border-theme input-dark pr-10" readonly />
<input ref="sel" :value="str" :id="id" type="text" class="focus-border-theme input-dark !pr-10" readonly />
<!--Copy icon-->
<div class="absolute right-0 px-4">

View File

@@ -2,6 +2,7 @@
<div class="flex items-center justify-between px-6 pt-6 pb-6">
<div class="flex items-center">
<div class="mr-3">
<upload-cloud-icon v-if="icon === 'upload'" size="18" class="vue-feather text-theme" />
<corner-down-right-icon v-if="icon === 'move'" size="18" class="vue-feather text-theme" />
<share-icon v-if="icon === 'share'" size="18" class="vue-feather text-theme" />
<edit2-icon v-if="icon === 'edit'" size="18" class="vue-feather text-theme" />
@@ -23,6 +24,7 @@
<script>
import {
UploadCloudIcon,
CreditCardIcon,
KeyIcon,
UserPlusIcon,
@@ -39,6 +41,7 @@ export default {
name: 'PopupHeader',
props: ['title', 'icon'],
components: {
UploadCloudIcon,
CornerDownRightIcon,
CreditCardIcon,
UserPlusIcon,

View File

@@ -113,6 +113,13 @@ const itemHelpers = {
})
}
Vue.prototype.$createUploadRequest = function (entry) {
events.$emit('popup:open', {
name: 'create-upload-request',
item: entry,
})
}
Vue.prototype.$updateTeamFolder = function (entry) {
events.$emit('popup:open', {
name: 'update-team-folder',

View File

@@ -136,9 +136,9 @@
icon="user-plus"
/>
<Option
@click.native="$convertAsTeamFolder(item)"
@click.native="$createUploadRequest(item)"
v-if="isFolder"
:title="$t('Send Upload Request')"
:title="$t('Create Upload Request')"
icon="upload-cloud"
/>
</OptionGroup>

View File

@@ -40,7 +40,7 @@
/>
</MobileMultiSelectToolbar>
<ContextMenu>
<ContextMenu v-if="entries.length">
<template v-slot:empty-select>
<OptionGroup>
<OptionUpload :title="$t('actions.upload')" type="file" />
@@ -104,7 +104,7 @@
<div v-if="uploadRequest" class="relative mx-auto mb-8 w-24 text-center">
<VueFolderIcon class="inline-block w-28" />
<MemberAvatar
:member="uploadRequest.user"
:member="uploadRequest.data.relationships.user"
class="absolute -bottom-2.5 -right-2"
:is-border="true"
:size="32"
@@ -185,14 +185,15 @@ export default {
},
},
created() {
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('context-menu:current-folder', (folder) => (this.item = folder))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
//this.$store.dispatch('getFolder', this.$route.params.id)
this.$store.commit('LOADING_STATE', { loading: false, data: [] })
axios.get('/api/request').then((response) => this.$store.commit('SET_UPLOAD_REQUEST', response.data))
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('context-menu:current-folder', (folder) => (this.item = folder))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
axios.get(`/api/upload-request/${this.$router.currentRoute.params.token}`)
.then((response) => this.$store.commit('SET_UPLOAD_REQUEST', response.data))
},
}
</script>

View File

@@ -14,6 +14,7 @@
<ShareCreatePopup />
<ShareEditPopup />
<CreateUploadRequestPopup />
<CreateFolderPopup />
<RenameItemPopup />
<MoveItemPopup />
@@ -76,10 +77,12 @@ import DragUI from '../components/FilesView/DragUI'
import InfoSidebar from '../components/FilesView/InfoSidebar'
import { events } from '../bus'
import { mapGetters } from 'vuex'
import CreateUploadRequestPopup from "../components/Others/CreateUploadRequestPopup";
export default {
name: 'Platform',
components: {
CreateUploadRequestPopup,
CreateTeamFolderPopup,
PanelNavigationFiles,
EditTeamFolderPopup,

View File

@@ -5,13 +5,13 @@ namespace Domain\UploadRequest\Controllers;
use App\Http\Controllers\Controller;
use Auth;
use Domain\UploadRequest\Notifications\UploadRequestNotification;
use Domain\UploadRequest\Requests\StoreUploadRequest;
use Domain\UploadRequest\Resources\UploadRequestResource;
use Illuminate\Http\Request;
use Notification;
class CreateUploadRequestController extends Controller
{
public function __invoke(Request $request)
public function __invoke(StoreUploadRequest $request)
{
$uploadRequest = Auth::user()->uploadRequest()->create([
'folder_id' => $request->input('folder_id'),
@@ -19,8 +19,11 @@ class CreateUploadRequestController extends Controller
'notes' => $request->input('notes'),
]);
Notification::route('mail', $uploadRequest->email)
->notify(new UploadRequestNotification($uploadRequest));
// If user type email, notify by email
if ($uploadRequest->email) {
Notification::route('mail', $uploadRequest->email)
->notify(new UploadRequestNotification($uploadRequest));
}
return response(new UploadRequestResource($uploadRequest), 201);
}

View File

@@ -45,7 +45,7 @@ class UploadRequestNotification extends Notification implements ShouldQueue
->subject("{$this->uploadRequest->user->settings->first_name} Request You for File Upload")
->greeting('Hello')
->line("We are emailing you because {$this->uploadRequest->user->settings->first_name} needs files from you. Please click on the link below and upload your files for {$this->uploadRequest->user->settings->first_name}.")
->action('Upload Files', url('/'))
->action('Upload Files', url("/request/{$this->uploadRequest->id}/upload"))
->line('Thank you for using our application!');
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Domain\UploadRequest\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUploadRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' => 'sometimes|string',
'notes' => 'sometimes|string',
'folder_id' => 'required|string',
];
}
}

View File

@@ -1,4 +1,5 @@
<?php
namespace Domain\UploadRequest\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
@@ -12,16 +13,17 @@ class UploadRequestResource extends JsonResource
'id' => $this->id,
'type' => 'upload-request',
'attributes' => [
'folder_id' => $this->folder_id,
'status' => $this->status,
'email' => $this->email,
'notes' => $this->notes,
'folder_id' => $this->folder_id,
'status' => $this->status,
'email' => $this->email,
'notes' => $this->notes,
'url' => url("/request/$this->id/upload"),
],
'relationships' => [
'user' => [
'data' => [
'id' => $this->user->id,
'type' => 'user',
'id' => $this->user->id,
'type' => 'user',
'attributes' => [
'name' => $this->user->settings->name,
'avatar' => $this->user->settings->avatar,

View File

@@ -25,9 +25,10 @@ class DashboardTest extends TestCase
->assertStatus(200)
->assertExactJson([
'app' => [
'earnings' => '$0.00',
'license' => 'extended',
'version' => config('vuefilemanager.version'),
'earnings' => '$0.00',
'isRunningCron' => false,
'license' => 'extended',
'version' => config('vuefilemanager.version'),
],
'disk' => [
'download' => [

View File

@@ -24,7 +24,7 @@ class UploadRequestTest extends TestCase
/**
* @test
*/
public function user_create_upload_request()
public function user_create_upload_request_with_email()
{
$user = User::factory()
->hasSettings()
@@ -48,6 +48,32 @@ class UploadRequestTest extends TestCase
Notification::assertTimesSent(1, UploadRequestNotification::class);
}
/**
* @test
*/
public function user_create_upload_request_without_email()
{
$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...',
])
->assertCreated();
$this->assertDatabasehas('upload_requests', [
'folder_id' => '00cacdb9-1d09-4a32-8ad7-c0d45d66b758',
'notes' => 'Please send me your files...',
'email' => null,
]);
Notification::assertNothingSent();
}
/**
* @test
*/