finish file request

This commit is contained in:
Čarodej
2022-02-22 09:35:06 +01:00
parent 171ee5fa04
commit c3398f0da4
9 changed files with 185 additions and 113 deletions

View File

@@ -4,15 +4,16 @@
<NavigationBar />
<div class="flex items-center">
<!--I am Done-->
<div class="bg-theme-200 mr-6 flex cursor-pointer items-center rounded-lg py-1 pr-1 pl-4">
<b @click="uploadingDone" class="text-theme mr-3 text-xs">
{{ isDone ? $t('Awesome!') : $t('Tell Jane you are done!') }}
{{ $t('Tell Jane you are done!') }}
</b>
<img
class="w-8 rounded-lg"
src="http://192.168.1.112:8000/avatars/md-f45abbe5-962c-4229-aef2-9991e96d54d9.png"
alt="Avatar"
/>
<MemberAvatar
:member="uploadRequest.data.relationships.user"
:size="34"
/>
</div>
<!--Create button-->
@@ -89,6 +90,7 @@ import PopoverItem from '../Desktop/PopoverItem'
import UploadProgress from './UploadProgress'
import NavigationBar from './NavigationBar'
import ToolbarButton from './ToolbarButton'
import MemberAvatar from "./MemberAvatar"
import OptionUpload from './OptionUpload'
import OptionGroup from './OptionGroup'
import SearchBar from './SearchBar'
@@ -104,6 +106,7 @@ export default {
PopoverWrapper,
NavigationBar,
ToolbarButton,
MemberAvatar,
OptionUpload,
OptionGroup,
PopoverItem,
@@ -111,30 +114,22 @@ export default {
Option,
},
computed: {
...mapGetters(['isVisibleNavigationBars', 'currentTeamFolder', 'currentFolder', 'sharedDetail', 'clipboard']),
canEdit() {
return this.sharedDetail && this.sharedDetail.data.attributes.permission === 'editor'
},
...mapGetters(['isVisibleNavigationBars', 'currentTeamFolder', 'currentFolder', 'sharedDetail', 'clipboard', 'uploadRequest']),
canManipulate() {
return this.clipboard[0]
},
},
data() {
return {
isDone: false,
}
},
methods: {
uploadingDone() {
// TODO: add name to the message
if (!this.isDone) {
events.$emit('toaster', {
type: 'success',
message: this.$t('We notified Jane about your new uploads successfully.'),
})
}
this.isDone = true
events.$emit('confirm:open', {
title: this.$t('Are you sure you uploaded all files you want for {name}?', {name: this.uploadRequest.relationships.user.data.attributes.name}),
message: this.$t("You won't be able to upload any files here once again."),
action: {
id: this.$router.currentRoute.params.token,
operation: 'close-upload-request',
},
})
},
showCreateMenu() {
events.$emit('popover:open', 'desktop-create')

View File

@@ -146,7 +146,7 @@ const actions = {
return new Promise((resolve, reject) => {
// Get route
let route = {
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}`,
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}/upload`,
Public: `/api/editor/upload/${router.currentRoute.params.token}`,
}[router.currentRoute.name] || '/api/upload'

View File

@@ -9,8 +9,7 @@ const defaultState = {
}
const actions = {
getUploadRequestDetail: ({ commit, getters }) => {
getUploadRequestDetail: ({ commit }) => {
axios.get(`/api/upload-request/${router.currentRoute.params.token}`)
.then((response) => {
@@ -24,6 +23,15 @@ const actions = {
}
})
},
closeUploadRequest: ({ commit }) => {
axios
.delete(`/api/upload-request/${router.currentRoute.params.token}`)
.then((response) => {
commit('LOADING_STATE', { loading: false, data: [] })
commit('SET_UPLOAD_REQUEST', response.data)
})
.catch(() => this.$isSomethingWrong())
},
}
const mutations = {

View File

@@ -15,29 +15,29 @@
</OptionGroup>
<OptionGroup :title="$t('Create')">
<Option
@click.stop.native="createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
:is-hover-disabled="true"
/>
@click.stop.native="createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
:is-hover-disabled="true"
/>
</OptionGroup>
</MobileCreateMenu>
<MobileMultiSelectToolbar>
<ToolbarButton
@click.native="$moveFileOrFolder(clipboard)"
class="action-btn"
source="move"
:action="$t('actions.move')"
:class="{ 'is-inactive': clipboard.length < 1 }"
/>
@click.native="$moveFileOrFolder(clipboard)"
class="action-btn"
source="move"
:action="$t('actions.move')"
:class="{ 'is-inactive': clipboard.length < 1 }"
/>
<ToolbarButton
@click.native="$deleteFileOrFolder(clipboard)"
class="action-btn"
source="trash"
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
@click.native="$deleteFileOrFolder(clipboard)"
class="action-btn"
source="trash"
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
</MobileMultiSelectToolbar>
<ContextMenu v-if="entries.length">
@@ -48,20 +48,20 @@
</OptionGroup>
<OptionGroup>
<Option
@click.native="$createFolder"
:title="$t('context_menu.create_folder')"
icon="create-folder"
/>
@click.native="$createFolder"
:title="$t('context_menu.create_folder')"
icon="create-folder"
/>
</OptionGroup>
</template>
<template v-slot:single-select v-if="item">
<OptionGroup>
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
@@ -86,10 +86,10 @@
{{ $t('Spotlight') }}
</MobileActionButton>
<MobileActionButton
@click.native="$showMobileMenu('create-list')"
v-if="$checkPermission(['master', 'editor'])"
icon="cloud-plus"
>
@click.native="$showMobileMenu('create-list')"
v-if="$checkPermission(['master', 'editor'])"
icon="cloud-plus"
>
{{ $t('mobile.create') }}
</MobileActionButton>
<MobileActionButton @click.native="$enableMultiSelectMode" icon="check-square">
@@ -100,28 +100,26 @@
</MobileActionButton>
</FileActionsMobile>
<EmptyFilePage>
<div v-if="uploadRequest" class="relative mx-auto mb-8 w-24 text-center">
<EmptyFilePage v-if="uploadRequest">
<div class="relative mx-auto mb-8 w-24 text-center">
<VueFolderIcon class="inline-block w-28" />
<MemberAvatar
:member="uploadRequest.data.relationships.user"
class="absolute -bottom-2.5 -right-2"
:is-border="true"
:size="32"
/>
v-if="uploadRequest.data.attributes.status !== 'expired'"
:member="uploadRequest.data.relationships.user"
class="absolute -bottom-2.5 -right-2"
:is-border="true"
:size="32"
/>
</div>
<h1 class="title">
{{ $t('Jane Request You for File Upload') }}
{{ emptyPageTitle }}
</h1>
<p class="description max-w-[420px]">
{{
$t(
'Your files will be uploaded automatically and after that, you can organize your files in folders.'
)
}}
{{ emptyPageDescription }}
</p>
<ButtonUpload button-style="theme">
<ButtonUpload v-if="uploadRequest.data.attributes.status === 'active'" button-style="theme">
{{ $t('empty_page.call_to_action') }}
</ButtonUpload>
</EmptyFilePage>
@@ -146,51 +144,65 @@ import FileBrowser from '../../components/FilesView/FileBrowser'
import ContextMenu from '../../components/FilesView/ContextMenu'
import OptionGroup from '../../components/FilesView/OptionGroup'
import Option from '../../components/FilesView/Option'
import { events } from '../../bus'
import { mapGetters } from 'vuex'
import {events} from '../../bus'
import {mapGetters} from 'vuex'
export default {
name: 'Files',
components: {
MobileMultiSelectToolbar,
MobileActionButton,
FileActionsMobile,
MobileContextMenu,
MobileCreateMenu,
EmptyFilePage,
VueFolderIcon,
ToolbarButton,
MemberAvatar,
ButtonUpload,
OptionUpload,
OptionGroup,
FileBrowser,
ContextMenu,
Option,
},
computed: {
...mapGetters(['fastPreview', 'clipboard', 'config', 'user', 'entries', 'uploadRequest']),
isFolder() {
return this.item && this.item.data.type === 'folder'
},
},
data() {
return {
item: undefined,
}
},
methods: {
createFolder() {
events.$emit('popup:open', { name: 'create-folder' })
},
},
created() {
name: 'Files',
components: {
MobileMultiSelectToolbar,
MobileActionButton,
FileActionsMobile,
MobileContextMenu,
MobileCreateMenu,
EmptyFilePage,
VueFolderIcon,
ToolbarButton,
MemberAvatar,
ButtonUpload,
OptionUpload,
OptionGroup,
FileBrowser,
ContextMenu,
Option,
},
computed: {
...mapGetters(['fastPreview', 'clipboard', 'config', 'user', 'entries', 'uploadRequest']),
isFolder() {
return this.item && this.item.data.type === 'folder'
},
emptyPageTitle() {
// Todo: add name into translation
return {
active: this.$t('Jane Request You for File Upload'),
filled: this.$t('Upload Request was Fulfilled Successfully'),
expired: this.$t('Upload Request Expired'),
}[this.uploadRequest.data.attributes.status]
},
emptyPageDescription() {
return {
active: this.$t('Your files will be uploaded automatically and after that, you can organize your files in folders.'),
filled: this.$t('This upload request is no longer available for uploading files.'),
expired: this.$t('This upload request is no longer available for uploading files.'),
}[this.uploadRequest.data.attributes.status]
}
},
data() {
return {
item: undefined,
}
},
methods: {
createFolder() {
events.$emit('popup:open', {name: 'create-folder'})
},
},
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('getUploadRequestDetail')
},
this.$store.dispatch('getUploadRequestDetail')
},
}
</script>

View File

@@ -4,6 +4,8 @@
<FilePreview />
<Spotlight />
<ConfirmPopup />
<!--Popups-->
<CreateFolderPopup />
<RenameItemPopup />
@@ -42,6 +44,7 @@ import FileSortingMobile from '../components/FilesView/FileSortingMobile'
import FileFilterMobile from '../components/FilesView/FileFilterMobile'
import CreateFolderPopup from '../components/Others/CreateFolderPopup'
import DesktopToolbar from '../components/FilesView/DesktopToolbar'
import ConfirmPopup from "../components/Others/Popup/ConfirmPopup"
import RenameItemPopup from '../components/Others/RenameItemPopup'
import MobileToolbar from '../components/FilesView/MobileToolbar'
import FilePreview from '../components/FilePreview/FilePreview'
@@ -55,6 +58,7 @@ import { events } from '../bus'
export default {
name: 'UploadRequest',
components: {
ConfirmPopup,
DesktopUploadRequestToolbar,
CreateFolderPopup,
FileSortingMobile,
@@ -85,6 +89,11 @@ export default {
// TODO: new scaledown effect
events.$on('mobile-menu:show', () => (this.isScaledDown = true))
events.$on('mobile-menu:hide', () => (this.isScaledDown = false))
events.$on('action:confirmed', (data) => {
if (data.operation === 'close-upload-request')
this.$store.dispatch('closeUploadRequest')
})
},
}
</script>

View File

@@ -2,10 +2,12 @@
use Domain\UploadRequest\Controllers\GetUploadRequestController;
use Domain\UploadRequest\Controllers\CreateUploadRequestController;
use Domain\UploadRequest\Controllers\SetUploadRequestAsFilledController;
use Domain\UploadRequest\Controllers\UploadFilesForUploadRequestController;
Route::get('/{uploadRequest}', GetUploadRequestController::class);
Route::post('/{uploadRequest}', UploadFilesForUploadRequestController::class);
Route::delete('/{uploadRequest}', SetUploadRequestAsFilledController::class);
Route::post('/{uploadRequest}/upload', UploadFilesForUploadRequestController::class);
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('/', CreateUploadRequestController::class);

View File

@@ -0,0 +1,21 @@
<?php
namespace Domain\UploadRequest\Controllers;
use Domain\UploadRequest\Models\UploadRequest;
use Domain\UploadRequest\Resources\UploadRequestResource;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Response;
class SetUploadRequestAsFilledController
{
public function __invoke(UploadRequest $uploadRequest): Response|Application|ResponseFactory
{
$uploadRequest->update([
'status' => 'filled',
]);
return response(new UploadRequestResource($uploadRequest), 201);
}
}

View File

@@ -28,7 +28,7 @@ class UploadRequestResource extends JsonResource
'id' => $this->user->id,
'type' => 'user',
'attributes' => [
'name' => $this->user->settings->name,
'name' => $this->user->settings->first_name,
'avatar' => $this->user->settings->avatar,
],
],

View File

@@ -1,4 +1,5 @@
<?php
namespace Tests\Domain\UploadRequest;
use Storage;
@@ -118,7 +119,7 @@ class UploadRequestTest extends TestCase
->create('fake-file.pdf', 12000000, 'application/pdf');
$this
->postJson("/api/upload-request/$uploadRequest->id", [
->postJson("/api/upload-request/$uploadRequest->id/upload", [
'filename' => $file->name,
'file' => $file,
'parent_id' => null,
@@ -159,7 +160,7 @@ class UploadRequestTest extends TestCase
->create('fake-file.pdf', 12000000, 'application/pdf');
$this
->postJson("/api/upload-request/$uploadRequest->id", [
->postJson("/api/upload-request/$uploadRequest->id/upload", [
'filename' => $file->name,
'file' => $file,
'parent_id' => null,
@@ -167,4 +168,28 @@ class UploadRequestTest extends TestCase
'is_last' => 'true',
])->assertStatus(410);
}
/**
* @test
*/
public function it_mark_upload_request_as_filled()
{
$user = User::factory()
->hasSettings()
->create();
$uploadRequest = UploadRequest::factory()
->create([
'status' => 'active',
'user_id' => $user->id,
]);
$this
->deleteJson("/api/upload-request/$uploadRequest->id")
->assertStatus(201)
->assertJsonFragment([
'id' => $uploadRequest->id,
'status' => 'filled',
]);
}
}