diff --git a/config/vuefilemanager.php b/config/vuefilemanager.php
index 580ae9ee..784818f8 100644
--- a/config/vuefilemanager.php
+++ b/config/vuefilemanager.php
@@ -61,6 +61,10 @@ return [
],
],
+ 'paginate' => [
+ 'perPage' => 8,
+ ],
+
// The update versions which need to run upgrade process
'updates' => [
'2_0_10',
diff --git a/package.json b/package.json
index 74015fb8..faeff722 100644
--- a/package.json
+++ b/package.json
@@ -23,26 +23,26 @@
"resolve-url-loader": "^2.3.1",
"sass": "^1.49.11",
"sass-loader": "^8.0.2",
- "tailwindcss": "^3.0.23",
+ "tailwindcss": "^3.0.24",
"tailwindcss-debug-screens": "^2.2.1",
"vue-loader": "^15.9.8",
"vue-template-compiler": "^2.6.14"
},
"dependencies": {
"@paypal/paypal-js": "^4.2.2",
- "@stripe/stripe-js": "^1.26.0",
+ "@stripe/stripe-js": "^1.29.0",
"lodash": "^4.17.21",
"node-sass": "^4.14.1",
"pdfvuer": "^1.9.2",
"tailwind-scrollbar-hide": "^1.1.7",
"twemoji": "^13.1.1",
- "v-click-outside": "^3.1.2",
+ "v-click-outside": "^3.2.0",
"vee-validate": "^3.4.14",
"vue": "^2.6.14",
"vue-feather-icons": "^5.1.0",
"vue-i18n": "^8.27.1",
"vue-recaptcha-v3": "^1.9.0",
- "vue-router": "^3.5.3",
+ "vue-router": "^3.5.4",
"vuex": "^3.6.2"
}
}
diff --git a/resources/js/components/EntriesView/FileBrowser.vue b/resources/js/components/EntriesView/FileBrowser.vue
index 7aea977c..c440e801 100644
--- a/resources/js/components/EntriesView/FileBrowser.vue
+++ b/resources/js/components/EntriesView/FileBrowser.vue
@@ -11,6 +11,7 @@
@dragover="dragEnter"
@dragleave="dragLeave"
@dragover.prevent
+ @scroll="infiniteScroll"
tabindex="-1"
@click.self="deselect"
>
@@ -24,6 +25,15 @@
:key="item.data.id"
:item="item"
/>
+
+
+
+
+
@@ -31,14 +41,17 @@
import ItemHandler from './ItemHandler'
import { events } from '../../bus'
import { mapGetters } from 'vuex'
+import Spinner from './Spinner'
+import { debounce } from 'lodash'
export default {
name: 'FileBrowser',
components: {
ItemHandler,
+ Spinner
},
computed: {
- ...mapGetters(['isVisibleSidebar', 'currentFolder', 'itemViewType', 'clipboard', 'entries', 'config']),
+ ...mapGetters(['isVisibleSidebar', 'currentFolder', 'itemViewType', 'clipboard', 'entries', 'config', 'paginate']),
draggedItems() {
// Set opacity for dragged items
if (!this.clipboard.includes(this.draggingId)) {
@@ -49,14 +62,39 @@ export default {
return this.clipboard
}
},
+ canLoadMoreEntries() {
+ return this.paginate?.currentPage !== this.paginate?.lastPage
+ },
+ showInfiniteLoadSpinner() {
+ return this.canLoadMoreEntries && this.entries.length !== 0 && this.paginate.perPage <= this.entries.length
+ },
},
data() {
return {
draggingId: undefined,
isDragging: false,
+ isLoadingNewEntries: false,
}
},
methods: {
+ infiniteScroll: debounce(function () {
+ if (this.isInfinityLoaderAtBottomPage() && this.canLoadMoreEntries && !this.isLoadingNewEntries) {
+ this.isLoadingNewEntries = true
+
+ this.$getDataByLocation(this.paginate.currentPage + 1)
+ .then(() => this.isLoadingNewEntries = false)
+ }
+ }, 150),
+ isInfinityLoaderAtBottomPage() {
+ let rect = this.$refs.infinityLoader.getBoundingClientRect()
+
+ return (
+ rect.bottom > 0 &&
+ rect.right > 0 &&
+ rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
+ rect.top < (window.innerHeight || document.documentElement.clientHeight)
+ );
+ },
deleteItems() {
if ((this.clipboard.length > 0 && this.$checkPermission('master')) || this.$checkPermission('editor')) {
this.$store.dispatch('deleteItem')
@@ -81,7 +119,7 @@ export default {
// Store dragged folder
this.draggingId = data
- // TODO: founded issue on firefox
+ // TODO: found issue on firefox
},
dragFinish(data, event) {
if (event.dataTransfer.items.length === 0) {
@@ -131,6 +169,11 @@ export default {
},
},
created() {
+ // Track document scrolling to load new entries if needed
+ if (window.innerWidth <= 1024) {
+ document.addEventListener('scroll', this.infiniteScroll)
+ }
+
events.$on('drop', () => {
this.isDragging = false
diff --git a/resources/js/components/EntriesView/NavigationSharePanel.vue b/resources/js/components/EntriesView/NavigationSharePanel.vue
index d137a5a2..40267560 100644
--- a/resources/js/components/EntriesView/NavigationSharePanel.vue
+++ b/resources/js/components/EntriesView/NavigationSharePanel.vue
@@ -115,7 +115,7 @@ export default {
'isDarkMode',
]),
favourites() {
- return this.user.data.relationships.favourites.data.attributes.folders
+ return this.user.data.relationships.favourites.attributes.folders
},
storage() {
return this.$store.getters.user.data.attributes.storage
diff --git a/resources/js/components/EntriesView/PanelNavigationFiles.vue b/resources/js/components/EntriesView/PanelNavigationFiles.vue
index 3c4d2fbc..ba212d44 100644
--- a/resources/js/components/EntriesView/PanelNavigationFiles.vue
+++ b/resources/js/components/EntriesView/PanelNavigationFiles.vue
@@ -132,7 +132,7 @@ export default {
computed: {
...mapGetters(['isVisibleNavigationBars', 'navigation', 'clipboard', 'config', 'user']),
favourites() {
- return this.user.data.relationships.favourites.data
+ return this.user.data.relationships.favourites
},
storage() {
return this.$store.getters.user.data.attributes.storage
diff --git a/resources/js/components/Spotlight/Spotlight.vue b/resources/js/components/Spotlight/Spotlight.vue
index 80855f64..ed3e5e0c 100644
--- a/resources/js/components/Spotlight/Spotlight.vue
+++ b/resources/js/components/Spotlight/Spotlight.vue
@@ -900,13 +900,13 @@ export default {
.then((response) => {
// Show user result
if (this.activeFilter === 'users') {
- this.results = response.data.data
+ this.results = response.data
}
// Show file result
if (!this.activeFilter) {
- let files = response.data.files.data
- let folders = response.data.folders.data
+ let files = response.data.files
+ let folders = response.data.folders
this.results = folders.concat(files)
}
diff --git a/resources/js/helpers/functionHelpers.js b/resources/js/helpers/functionHelpers.js
index 8cba68aa..a2d39754 100644
--- a/resources/js/helpers/functionHelpers.js
+++ b/resources/js/helpers/functionHelpers.js
@@ -350,19 +350,19 @@ const FunctionHelpers = {
}[this.$router.currentRoute.name]
}
- Vue.prototype.$getDataByLocation = function () {
+ Vue.prototype.$getDataByLocation = async function (page) {
let routes = {
- RequestUpload: ['getUploadRequestFolder', router.currentRoute.params.id || undefined ],
- Public: ['getSharedFolder', router.currentRoute.params.id || undefined],
- Files: ['getFolder', router.currentRoute.params.id || undefined],
- RecentUploads: ['getRecentUploads'],
- MySharedItems: ['getMySharedItems'],
- Trash: ['getTrash', router.currentRoute.params.id || undefined],
- TeamFolders: ['getTeamFolder', router.currentRoute.params.id || undefined],
- SharedWithMe: ['getSharedWithMeFolder', router.currentRoute.params.id || undefined],
+ RequestUpload: ['getUploadRequestFolder', {page:page, id:router.currentRoute.params.id || undefined} ],
+ Public: ['getSharedFolder', {page:page, id:router.currentRoute.params.id || undefined}],
+ Files: ['getFolder', {page:page, id:router.currentRoute.params.id || undefined}],
+ RecentUploads: ['getRecentUploads', page],
+ MySharedItems: ['getMySharedItems', page],
+ Trash: ['getTrash', {page:page , id:router.currentRoute.params.id || undefined}],
+ TeamFolders: ['getTeamFolder',{page:page, id:router.currentRoute.params.id || undefined}],
+ SharedWithMe: ['getSharedWithMeFolder',{page:page, id:router.currentRoute.params.id || undefined}],
}
- store.dispatch(...routes[router.currentRoute.name])
+ await store.dispatch(...routes[router.currentRoute.name])
}
Vue.prototype.$getPaymentLogo = function (driver) {
diff --git a/resources/js/helpers/itemHelpers.js b/resources/js/helpers/itemHelpers.js
index 635272d0..da1dcaa5 100644
--- a/resources/js/helpers/itemHelpers.js
+++ b/resources/js/helpers/itemHelpers.js
@@ -17,7 +17,7 @@ const itemHelpers = {
}
Vue.prototype.$toggleFavourites = function (entry) {
- let favourites = store.getters.user.data.relationships.favourites.data
+ let favourites = store.getters.user.data.relationships.favourites
// Check if folder is in favourites and then add/remove from favourites
if (favourites && !favourites.find((el) => el.data.id === entry.data.id)) {
diff --git a/resources/js/store/modules/fileBrowser.js b/resources/js/store/modules/fileBrowser.js
index 26718974..f77564f3 100644
--- a/resources/js/store/modules/fileBrowser.js
+++ b/resources/js/store/modules/fileBrowser.js
@@ -6,45 +6,50 @@ import i18n from '../../i18n'
const defaultState = {
currentFolder: undefined,
+ isMultiSelectMode: false,
fastPreview: undefined,
navigation: undefined,
- isMultiSelectMode: false,
+ paginate: undefined,
isLoading: true,
clipboard: [],
entries: [],
}
const actions = {
- getFolder: ({ commit, getters }, id) => {
- commit('LOADING_STATE', { loading: true, data: [] })
+ getFolder: ({ commit, getters },{page, id}) => {
+ return new Promise ((resolve, reject) => {
+ if(! page)
+ commit('LOADING_STATE', { loading: true, data: [] })
- axios
- .get(`${getters.api}/browse/folders/${id || 'all'}${getters.sorting.URI}`)
- .then((response) => {
- let folders = response.data.folders.data
- let files = response.data.files.data
+ axios
+ .get(`${getters.api}/browse/folders/${id || 'all'}${getters.sorting.URI}&page=${currentPage}`)
+ .then((response) => {
+ commit('SET_PAGINATE', response.data.meta.paginate)
- commit('LOADING_STATE', {
- loading: false,
- data: folders.concat(files),
- })
- commit('SET_CURRENT_FOLDER', response.data.root)
-
- events.$emit('scrollTop')
- })
- .catch((error) => {
- // Redirect if unauthenticated
- if ([401, 403].includes(error.response.status)) {
- commit('SET_AUTHORIZED', false)
- router.push({ name: 'SignIn' })
- } else {
- // Show error message
- events.$emit('alert:open', {
- title: i18n.t('popup_error.title'),
- message: i18n.t('popup_error.message'),
+ commit('LOADING_STATE', {
+ loading: false,
+ data: response.data.data,
})
- }
- })
+ commit('SET_CURRENT_FOLDER', response.data.meta.root)
+
+ events.$emit('scrollTop')
+
+ resolve(response);
+ })
+ .catch((error) => {
+ // Redirect if unauthenticated
+ if ([401, 403].includes(error.response.status)) {
+ commit('SET_AUTHORIZED', false)
+ router.push({ name: 'SignIn' })
+ } else {
+ // Show error message
+ events.$emit('alert:open', {
+ title: i18n.t('popup_error.title'),
+ message: i18n.t('popup_error.message'),
+ })
+ }
+ })
+ })
},
getRecentUploads: ({ commit, getters }) => {
commit('LOADING_STATE', { loading: true, data: [] })
@@ -125,8 +130,15 @@ const actions = {
}
const mutations = {
+ SET_PAGINATE(state, payload) {
+ state.paginate = payload
+ },
LOADING_STATE(state, payload) {
- state.entries = payload.data
+ if(payload.data.length === 0) {
+ state.entries = []
+ } else {
+ state.entries.push(...payload.data)
+ }
state.isLoading = payload.loading
},
SET_CURRENT_FOLDER(state, folder) {
@@ -220,6 +232,7 @@ const getters = {
navigation: (state) => state.navigation,
clipboard: (state) => state.clipboard,
isLoading: (state) => state.isLoading,
+ paginate: (state) => state.paginate,
entries: (state) => state.entries,
}
diff --git a/resources/js/store/modules/uploadRequest.js b/resources/js/store/modules/uploadRequest.js
index 4bca2915..53ed3f01 100644
--- a/resources/js/store/modules/uploadRequest.js
+++ b/resources/js/store/modules/uploadRequest.js
@@ -15,8 +15,8 @@ const actions = {
axios
.get(`/api/file-request/${router.currentRoute.params.token}/browse/${id || 'all'}${getters.sorting.URI}`)
.then((response) => {
- let folders = response.data.folders.data
- let files = response.data.files.data
+ let folders = response.data.folders
+ let files = response.data.files
commit('LOADING_STATE', {
loading: false,
@@ -52,6 +52,11 @@ const actions = {
commit('SET_CURRENT_FOLDER', response.data.data.relationships.folder)
}
})
+ .catch((error) => {
+ Vue.prototype.$isSomethingWrong()
+
+ reject(error)
+ })
})
},
closeUploadRequest: ({ commit }) => {
diff --git a/resources/js/views/FileView/Files.vue b/resources/js/views/FileView/Files.vue
index 4294cdfb..e9707e73 100644
--- a/resources/js/views/FileView/Files.vue
+++ b/resources/js/views/FileView/Files.vue
@@ -254,7 +254,7 @@ export default {
return this.item && this.item.data.type === 'folder'
},
isInFavourites() {
- return this.user.data.relationships.favourites.data.find((el) => el.data.id === this.item.data.id)
+ return this.user.data.relationships.favourites.find((el) => el.data.id === this.item.data.id)
},
hasFile() {
return this.clipboard.find((item) => item.data.type !== 'folder')
@@ -266,7 +266,7 @@ export default {
}
},
created() {
- this.$store.dispatch('getFolder', this.$route.params.id)
+ this.$store.dispatch('getFolder', {page:null, id:this.$route.params.id})
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('context-menu:current-folder', (folder) => (this.item = folder))
diff --git a/resources/js/views/FileView/MySharedItems.vue b/resources/js/views/FileView/MySharedItems.vue
index 662a43d6..a3ef17c4 100644
--- a/resources/js/views/FileView/MySharedItems.vue
+++ b/resources/js/views/FileView/MySharedItems.vue
@@ -157,7 +157,7 @@ export default {
return this.item && this.item.type === 'folder'
},
isInFavourites() {
- return this.user.data.relationships.favourites.data.find((el) => el.id === this.item.id)
+ return this.user.data.relationships.favourites.find((el) => el.id === this.item.id)
},
hasFile() {
return this.clipboard.find((item) => item.type !== 'folder')
diff --git a/resources/js/views/FileView/Public.vue b/resources/js/views/FileView/Public.vue
index 637a8d6d..7a77ac6b 100644
--- a/resources/js/views/FileView/Public.vue
+++ b/resources/js/views/FileView/Public.vue
@@ -234,7 +234,7 @@ export default {
},
},
created() {
- this.$store.dispatch('getSharedFolder', this.$route.params.id)
+ this.$store.dispatch('getSharedFolder', {page:null, id:this.$route.params.id})
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
diff --git a/resources/js/views/FileView/SharedWithMe.vue b/resources/js/views/FileView/SharedWithMe.vue
index 17123ca4..63194ad5 100644
--- a/resources/js/views/FileView/SharedWithMe.vue
+++ b/resources/js/views/FileView/SharedWithMe.vue
@@ -242,7 +242,7 @@ export default {
},
},
mounted() {
- this.$store.dispatch('getSharedWithMeFolder', this.$route.params.id)
+ this.$store.dispatch('getSharedWithMeFolder',{page:null, id:this.$route.params.id})
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
@@ -257,7 +257,7 @@ export default {
if (this.$route.params.id) {
this.$router.push({ name: 'SharedWithMe' })
} else {
- this.$store.dispatch('getSharedWithMeFolder', undefined)
+ this.$store.dispatch('getSharedWithMeFolder',{page:null, id:undefined})
}
events.$emit('toaster', {
diff --git a/resources/js/views/FileView/TeamFolders.vue b/resources/js/views/FileView/TeamFolders.vue
index 2b41cbae..4752c2de 100644
--- a/resources/js/views/FileView/TeamFolders.vue
+++ b/resources/js/views/FileView/TeamFolders.vue
@@ -281,7 +281,7 @@ export default {
return this.item && this.item.data.type === 'folder'
},
isInFavourites() {
- return this.user.data.relationships.favourites.data.find((el) => el.id === this.item.id)
+ return this.user.data.relationships.favourites.find((el) => el.id === this.item.id)
},
hasFile() {
return this.clipboard.find((item) => item.type !== 'folder')
@@ -293,7 +293,7 @@ export default {
}
},
mounted() {
- this.$store.dispatch('getTeamFolder', this.$route.params.id)
+ this.$store.dispatch('getTeamFolder', {page:null, id:this.$route.params.id})
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
diff --git a/resources/js/views/FileView/Trash.vue b/resources/js/views/FileView/Trash.vue
index d2468cbc..3c6ced40 100644
--- a/resources/js/views/FileView/Trash.vue
+++ b/resources/js/views/FileView/Trash.vue
@@ -149,7 +149,7 @@ export default {
}
},
created() {
- this.$store.dispatch('getTrash', this.$route.params.id)
+ this.$store.dispatch('getTrash', {page:null, id:this.$route.params.id})
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
diff --git a/src/App/Users/Models/User.php b/src/App/Users/Models/User.php
index d63dfa55..1051d067 100644
--- a/src/App/Users/Models/User.php
+++ b/src/App/Users/Models/User.php
@@ -160,8 +160,7 @@ class User extends Authenticatable implements MustVerifyEmail
->with([
'parent:id,name',
'shared:token,id,item_id,permission,is_protected,expire_in',
- ])
- ->take(40);
+ ]);
}
/**
diff --git a/src/Domain/Browsing/Controllers/BrowseFolderController.php b/src/Domain/Browsing/Controllers/BrowseFolderController.php
index 82d94b9e..6a19e726 100644
--- a/src/Domain/Browsing/Controllers/BrowseFolderController.php
+++ b/src/Domain/Browsing/Controllers/BrowseFolderController.php
@@ -16,24 +16,49 @@ class BrowseFolderController
): array {
$root_id = Str::isUuid($id) ? $id : null;
+ $folderQuery = [
+ 'parent_id' => $root_id,
+ 'team_folder' => false,
+ 'user_id' => Auth::id(),
+ 'deleted_at' => null,
+ ];
+
+ $fileQuery = [
+ 'parent_id' => $root_id,
+ 'user_id' => Auth::id(),
+ 'deleted_at' => null,
+ ];
+
+ list($foldersTake, $foldersSkip, $filesTake, $filesSkip, $totalItemsCount) = getRecordsCount($folderQuery, $fileQuery, request()->input('page'));
+
$folders = Folder::with(['parent:id,name', 'shared:token,id,item_id,permission,is_protected,expire_in'])
- ->where('parent_id', $root_id)
- ->where('team_folder', false)
- ->where('user_id', Auth::id())
+ ->where($folderQuery)
->sortable()
+ ->skip($foldersSkip)
+ ->take($foldersTake)
->get();
-
+
$files = File::with(['parent:id,name', 'shared:token,id,item_id,permission,is_protected,expire_in'])
- ->where('parent_id', $root_id)
- ->where('user_id', Auth::id())
+ ->where($fileQuery)
->sortable()
+ ->skip($filesSkip)
+ ->take($filesTake)
->get();
+
+ $entries = collect([
+ $folders ? json_decode((new FolderCollection($folders))->toJson(), true) : null,
+ $files ? json_decode((new FilesCollection($files))->toJson(), true) : null,
+ ])->collapse();
+
+ list($paginate, $links) = generatePaginationCounts($totalItemsCount);
- // Collect folders and files to single array
return [
- 'folders' => new FolderCollection($folders),
- 'files' => new FilesCollection($files),
- 'root' => $root_id ? new FolderResource(Folder::findOrFail($root_id)) : null,
+ 'data' => $entries,
+ 'links' => $links,
+ 'meta' => [
+ 'paginate' => $paginate,
+ 'root' => $root_id ? new FolderResource(Folder::findOrFail($root_id)) : null,
+ ],
];
}
}
diff --git a/src/Domain/Browsing/Controllers/BrowseLatestFilesController.php b/src/Domain/Browsing/Controllers/BrowseLatestFilesController.php
index 1f1eb085..5572300b 100644
--- a/src/Domain/Browsing/Controllers/BrowseLatestFilesController.php
+++ b/src/Domain/Browsing/Controllers/BrowseLatestFilesController.php
@@ -2,12 +2,12 @@
namespace Domain\Browsing\Controllers;
use App\Users\Models\User;
+use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
-use Domain\Files\Resources\FilesCollection;
class BrowseLatestFilesController
{
- public function __invoke(): array
+ public function __invoke(Request $request): array
{
$user = User::with([
'latestUploads' => fn ($query) => $query->sortable(['created_at' => 'desc']),
@@ -15,9 +15,15 @@ class BrowseLatestFilesController
->where('id', Auth::id())
->first();
+ list($data, $paginate, $links) = groupPaginate($request, null, $user->latestUploads);
+
return [
- 'files' => new FilesCollection($user->latestUploads),
- 'root' => null,
+ 'data' => $data,
+ 'links' => $links,
+ 'meta' => [
+ 'paginate' => $paginate,
+ 'root' => null,
+ ],
];
}
}
diff --git a/src/Domain/Browsing/Controllers/BrowseSharedItemsController.php b/src/Domain/Browsing/Controllers/BrowseSharedItemsController.php
index 902af769..03282375 100644
--- a/src/Domain/Browsing/Controllers/BrowseSharedItemsController.php
+++ b/src/Domain/Browsing/Controllers/BrowseSharedItemsController.php
@@ -1,16 +1,15 @@
sortable()
->get();
+ list($data, $paginate, $links) = groupPaginate($request, $folders, $files);
+
// Collect folders and files to single array
return [
- 'folders' => new FolderCollection($folders),
- 'files' => new FilesCollection($files),
- 'root' => null,
+ 'data' => $data,
+ 'links' => $links,
+ 'meta' => [
+ 'paginate' => $paginate,
+ 'root' => null,
+ ],
];
}
}
diff --git a/src/Domain/Files/Resources/FilesCollection.php b/src/Domain/Files/Resources/FilesCollection.php
index 28f265a5..e2c50f93 100644
--- a/src/Domain/Files/Resources/FilesCollection.php
+++ b/src/Domain/Files/Resources/FilesCollection.php
@@ -1,16 +1,15 @@
$this->collection,
- ];
+ return $this->collection;
}
}
diff --git a/src/Domain/Folders/Resources/FolderCollection.php b/src/Domain/Folders/Resources/FolderCollection.php
index 5b00fcf3..4fd429c4 100644
--- a/src/Domain/Folders/Resources/FolderCollection.php
+++ b/src/Domain/Folders/Resources/FolderCollection.php
@@ -1,16 +1,15 @@
$this->collection,
- ];
+ return $this->collection;
}
}
diff --git a/src/Domain/Teams/Controllers/BrowseSharedWithMeController.php b/src/Domain/Teams/Controllers/BrowseSharedWithMeController.php
index 50cad2c0..f58bde7c 100644
--- a/src/Domain/Teams/Controllers/BrowseSharedWithMeController.php
+++ b/src/Domain/Teams/Controllers/BrowseSharedWithMeController.php
@@ -3,17 +3,16 @@ namespace Domain\Teams\Controllers;
use Str;
use Gate;
+use Illuminate\Http\Request;
use Domain\Files\Models\File;
use Domain\Folders\Models\Folder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
-use Domain\Files\Resources\FilesCollection;
use Domain\Folders\Resources\FolderResource;
-use Domain\Folders\Resources\FolderCollection;
class BrowseSharedWithMeController
{
- public function __invoke($id): array
+ public function __invoke(Request $request, $id): array
{
$id = Str::isUuid($id) ? $id : null;
@@ -46,11 +45,16 @@ class BrowseSharedWithMeController
->get();
}
+ list($data, $paginate, $links) = groupPaginate($request, $folders, $files ?? null);
+
return [
- 'root' => $id ? new FolderResource(Folder::findOrFail($id)) : null,
- 'folders' => new FolderCollection($folders),
- 'files' => isset($files) ? new FilesCollection($files) : new FilesCollection([]),
+ 'data' => $data,
'teamFolder' => $id ? new FolderResource($teamFolder) : null,
+ 'links' => $links,
+ 'meta' => [
+ 'paginate' => $paginate,
+ 'root' => $id ? new FolderResource(Folder::findOrFail($id)) : null,
+ ],
];
}
}
diff --git a/src/Domain/Teams/Controllers/TeamFoldersController.php b/src/Domain/Teams/Controllers/TeamFoldersController.php
index 9048cf45..97aea72d 100644
--- a/src/Domain/Teams/Controllers/TeamFoldersController.php
+++ b/src/Domain/Teams/Controllers/TeamFoldersController.php
@@ -2,6 +2,7 @@
namespace Domain\Teams\Controllers;
use Illuminate\Support\Str;
+use Illuminate\Http\Request;
use Domain\Files\Models\File;
use Domain\Folders\Models\Folder;
use Illuminate\Http\JsonResponse;
@@ -10,10 +11,8 @@ use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Domain\Teams\Models\TeamFolderMember;
use Domain\Teams\DTO\CreateTeamFolderData;
-use Domain\Files\Resources\FilesCollection;
use Domain\Folders\Resources\FolderResource;
use Domain\Teams\Actions\UpdateMembersAction;
-use Domain\Folders\Resources\FolderCollection;
use Domain\Teams\Actions\UpdateInvitationsAction;
use Domain\Teams\Requests\CreateTeamFolderRequest;
use Domain\Teams\Requests\UpdateTeamFolderMembersRequest;
@@ -28,7 +27,7 @@ class TeamFoldersController extends Controller
) {
}
- public function show($id): array
+ public function show(Request $request, $id): array
{
$id = Str::isUuid($id) ? $id : null;
@@ -51,12 +50,17 @@ class TeamFoldersController extends Controller
->get();
}
+ list($data, $paginate, $links) = groupPaginate($request, $folders, $files ?? null);
+
// Collect folders and files to single array
return [
- 'folders' => new FolderCollection($folders),
- 'files' => isset($files) ? new FilesCollection($files) : new FilesCollection([]),
- 'root' => $id ? new FolderResource(Folder::findOrFail($id)) : null,
+ 'data' => $data,
'teamFolder' => $id ? new FolderResource(Folder::findOrFail($id)->getLatestParent()) : null,
+ 'links' => $links,
+ 'meta' => [
+ 'paginate' => $paginate,
+ 'root' => $id ? new FolderResource(Folder::findOrFail($id)) : null,
+ ],
];
}
diff --git a/src/Support/helpers.php b/src/Support/helpers.php
index 6ecd7143..27e8046d 100644
--- a/src/Support/helpers.php
+++ b/src/Support/helpers.php
@@ -9,6 +9,7 @@ use Domain\Files\Models\File;
use Domain\Sharing\Models\Share;
use Domain\Folders\Models\Folder;
use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\DB;
use Domain\Settings\Models\Setting;
use Illuminate\Support\Facades\Http;
use Illuminate\Database\Eloquent\Model;
@@ -1208,4 +1209,93 @@ if (! function_exists('extractItemsFromGetAttribute')) {
];
});
}
+
+ if (! function_exists('generatePaginationCounts')) {
+ /**
+ * Group paginate of Foldes and Files
+ */
+ function generatePaginationCounts(
+ int $totalItemsCount
+ ) : array {
+ $perPage = config('vuefilemanager.paginate.perPage');
+ $currentPage = request()->input('page') === 'all' ? 1 : (int) request()->input('page');
+
+ $uri = request()->fullUrl();
+ $lastPage = ceil($totalItemsCount / $perPage);
+
+ return [
+ [
+ 'currentPage' => $currentPage,
+ 'from' => 1,
+ 'lastPage' => $lastPage,
+ 'path' => $uri,
+ 'perPage' => $perPage,
+ 'to' => $perPage,
+ 'total' => $totalItemsCount,
+ ],
+ [
+ 'first' => $uri . '&page=1',
+ 'last' => $uri . '&page=' . $lastPage,
+ 'next' => $currentPage == $lastPage ? null : $uri . '&page=' . $currentPage + 1,
+ 'prev' => $currentPage == 1 ? null : $uri . '&page=' . $currentPage - 1,
+ ],
+ ];
+ }
+ }
+
+ if (! function_exists('getRecordsCount')) {
+ /**
+ * Get count of items from the Database
+ */
+ function getRecordsCount(
+ array $folderQuery,
+ array $fileQuery,
+ string $page
+ ) : array {
+ $perPage = config('vuefilemanager.paginate.perPage');
+ $currentPage = $page === 'all' ? 1 : (int) $page;
+
+ $foldersSkip = 0;
+ $foldersTake = 0;
+ $filesSkip = 0;
+ $filesTake = 0;
+
+ $foldersCount = DB::table('folders')
+ ->where($folderQuery)
+ ->count();
+
+ $filesCount = DB::table('files')
+ ->where($fileQuery)
+ ->count();
+
+ $totalItemsCount = $foldersCount + $filesCount;
+
+ if ($page !== 'all') {
+ // Folders pages
+ if ($foldersCount >= $currentPage * $perPage) {
+ $foldersTake = $perPage;
+ $foldersSkip = ($currentPage - 1) * $perPage;
+ }
+
+ // Mixed page
+ if ($foldersCount < $currentPage * $perPage && ceil($currentPage) === ceil($foldersCount / $perPage)) {
+ $foldersSkip = ($currentPage - 1) * $perPage;
+ $foldersTake = $foldersCount - $foldersSkip;
+ $filesTake = ($currentPage * $perPage) - $foldersCount;
+ $filesSkip = 0;
+ }
+
+ // Files pages
+ if ($currentPage > ceil($foldersCount / $perPage)) {
+ $filesTake = $perPage;
+ $filesSkip = ((ceil($foldersCount / $perPage) * $perPage) - $foldersCount) + ($currentPage - (ceil($foldersCount / $perPage)) - 1) * $perPage;
+ }
+ } else {
+ $foldersTake = $foldersCount;
+ $filesTake = $filesCount;
+ }
+
+ return [$foldersTake, $foldersSkip, $filesTake, $filesSkip, $totalItemsCount];
+ }
+ }
}
diff --git a/tests/Support/Helpers/HelperTest.php b/tests/Support/Helpers/HelperTest.php
index c5d156d9..6c44ea0b 100644
--- a/tests/Support/Helpers/HelperTest.php
+++ b/tests/Support/Helpers/HelperTest.php
@@ -2,6 +2,10 @@
namespace Tests\Support\Helpers;
use Tests\TestCase;
+use App\Users\Models\User;
+use Domain\Files\Models\File;
+use Domain\Folders\Models\Folder;
+use Illuminate\Support\Facades\Config;
class HelperTest extends TestCase
{
@@ -25,4 +29,57 @@ class HelperTest extends TestCase
$this->assertEquals('Jane', $thirdTest['first_name']);
$this->assertEquals('', $thirdTest['last_name']);
}
+
+ /**
+ * @test
+ */
+ public function it_test_get_records_count()
+ {
+ $user = User::factory()
+ ->hasSettings()
+ ->create();
+
+ Folder::factory()
+ ->count(12)
+ ->create([
+ 'user_id' => $user->id,
+ 'parent_id' => null,
+ ]);
+
+ File::factory()
+ ->count(13)
+ ->create([
+ 'user_id' => $user->id,
+ 'parent_id' => null,
+ ]);
+
+ $folderQuery = [
+ 'parent_id' => null,
+ 'team_folder' => false,
+ 'user_id' => $user->id,
+ 'deleted_at' => null,
+ ];
+
+ $fileQuery = [
+ 'parent_id' => null,
+ 'user_id' => $user->id,
+ 'deleted_at' => null,
+ ];
+
+ Config::set('vuefilemanager.paginate.perPage', 5);
+
+ // getRecordsCunt returned array [foldersTake, foldersSkip, filesTake, filesSkip, totalItemsCount]
+
+ // Get folders page
+ $this->assertEquals([5, 0, 0, 0, 25], getRecordsCount($folderQuery, $fileQuery, '1'));
+
+ // Get mixed page
+ $this->assertEquals([2, 10, 3, 0, 25], getRecordsCount($folderQuery, $fileQuery, '3'));
+
+ // Get files page
+ $this->assertEquals([0, 0, 5, 8, 25], getRecordsCount($folderQuery, $fileQuery, '5'));
+
+ // Get all pages
+ $this->assertEquals([12, 0, 13, 0, 25], getRecordsCount($folderQuery, $fileQuery, 'all'));
+ }
}