Compare commits

..

11 Commits

Author SHA1 Message Date
Čarodej
36c5e51b4f refactoring 2022-05-24 10:01:07 +02:00
Milos Holba
f75c20e5a7 added test for getRecordsCount, format code 2022-05-02 18:21:20 +02:00
Milos Holba
ad8793ce28 change of the browsing functionality 2022-04-14 16:25:57 +02:00
Milos Holba
d71e598758 added possibility to return all record 2022-04-07 12:56:01 +02:00
Milos Holba
4379daa079 added infinite scroll in browsing 2022-04-06 17:40:44 +02:00
Čarodej
5531be6640 - language fix
- move item popup fix
2022-03-21 11:56:31 +01:00
Čarodej
1d144d6c9e notification mobile fix 2022-03-21 09:38:15 +01:00
Čarodej
b043878eed chunk upload fix 2022-03-21 09:35:13 +01:00
Čarodej
a2d0b26b68 language fix 2022-03-21 08:34:59 +01:00
Čarodej
381a440c61 codecanyon images 2022-03-20 22:10:45 +01:00
Čarodej
95efdc3993 changelog 2022-03-20 21:41:55 +01:00
70 changed files with 1007 additions and 515 deletions

View File

@@ -1,6 +1,6 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:YxwN4ge+hJYN/J9RTxCcgUdPZ3zBMUVWmzU71vwjU9Y=
APP_KEY=base64:YE2Zo20UvRL3LkRLr54PjlayHUCoDEGVICIq76iFZlU=
APP_DEBUG=true
APP_URL=http://localhost
APP_DEMO=false

View File

@@ -1,6 +1,157 @@
## Version 2.0
#### Release date: 1. January 2022
Changelog
### File Preview
User Interface
- Fullscreen mode can be set by double arrow icon on top of navigation sidebar in file page or by action in spotlight
- In mobile version you can now by opening image or document move seamlessly to another by swipe gesture
- Emoji picker was redesigned and now offer better experience to pick your favourite emoji for your folder icon
- Actions like create folder, upload files and any others was moved and grouped by 'Frequently used' and 'Others' category under single button
- User profile, Dashboard and other admin pages was redesigned
- Mac users can now switch between native emojis and twemojis
- New button to switch between dark/light mode was added under the main navigation in desktop
- Now when you undo in your browser, it goes back to the previous folder
- Application now generate multiple image sizes for better loading performance and is also frugal to your total data transfer
Spotlight
- Search through your files and folders
- Can be used as quick navigation through your folders or app pages
- Ability to search actions like toggle emojis, toggle dark/light mode, creating file request, new user and many more
- Search your users by activating user filter with keyboard shortcut (u+space)
- Ability to call spotlight with cmd/ctrl + k from any location in app like admin or user profile
- Ability from any location in the app to show document, image or video in file preview component
- Ability to use keyboard shortcuts to navigate in spotlight like arrow up/down, enter
Collaboration
- New Team Folders and Shared with Me categories
- Ability to create new team folder and invite users by email invitation, or if user is app user, then push notification will be sent as well.
- Ability to convert existing folder into Team Folder and invite members into it.
- Ability to dissolve your team folder. All members permissions will be revoked and your folder will be moved into My Files category.
- Ability to leave folder if you are member of someone team folder
- Received invitation can be accepted or declined
- User avatar indicate in file icon who is the owner of the file
- New team heads icon in desktop and mobile toolbar to indicate team members in the team folder
Metered Billing
- New metered billing where user can be charged by what he uses.
- Bandwidth, storage, flat fee and members are optional features which can be charged, not required
- Native balance system from which user is charger at the end of current billing period
- User can fund his balance by PayPal and Paystack single payment option
- If Stripe payment method is allowed, user can register his credit card and all future payments for billing period will be automatically charged. If there is any credit in balance and is sufficient, then this amount will be preferred instead of credit card charging
- User has ability to add/delete his payment methods (only Stripe)
- Admin has ability to increase user balance with certain amount
- Ability to set registration bonus for every new user registration
- User can set billing alert with certain amount. When this amount will be reached, the notification will be sent.
- New Usage Estimates widget in user profile which provide price estimates for current billing period
- New transactions widget in user profile with usage history
Fixed Billing
- Plans with yearly billing period is now supported
- New subscription widget with subscription details in user profile
- New Payment Method widget to manage user credit cards (available only for Stripe)
- New popup component to subscribe or upgrade account plan
Notification Center
- Ability to see notifications by Unread and Read category
- Interactive notifications to seamlessly perform actions from it if needed
- If broadcasting is set, notifications will be received just in time and showed in bottom right corner of the app
- Ability to clear all notifications by button
Zip
- New on the fly zipping system zips files without additional storage usage
- User can now select any files with any folders and zip them together
Sharing
- Redesigned sharing popup component for better user experience
- Shared video file (.mp4) has now ability to play video in shared page
- Ability to get share link via QR code
- Ability to generate embeddable code with shared item (beta)
- App logo was added into single file share pages
File Request
- User can generate file request by opening context menu over single folder or call file request from spotlight
- Ability to set custom folder name if file request will be filled
- Ability to leave a message for guest
- Ability to send file request by email for certain email recipient
- Full-fledged reach UI for guests to upload and manage their files directly in file request
- Push notification about filled file request will be received for user
Folder Upload
- Now user can upload their folders. The same folder structure will be recreated in the app
User Settings
- New appearance option was added where user can set his theme mode by dark, light or based by system option
- New default emoji option was added where Apple user can switch between native emojis or twemoji
- 2fa setup challenge option was added. User can store and generate backup keys.
- New Personal Access Token section was added where user can generate access token for API requests.
- New 'Current Password' input was added into change password functionality
- New widget to track the latest upload and download was added into the Storage tab
- Storage usage widget was redesigned
- New Billing tab with all subscription related items was added
Login & Registration
- Email confirmation for new account registrations can be required
- Integrated database with more than 550 disposable temporary email services to automatically deny new account registrations
- Users can now set up 2 factor verification with their favourite authenticator app
- reCaptcha was added to provide security for your registration and contact form
- Social authentication was implemented with Facebook, Google and GitHub drivers
Adsense
- Adsense will be integrated into VueFileManager
- The ads are showing in 3 locations - File Viewport, Download Page and Homepage
Setup Wizard
- Server check before you running installation, it will show you if you had set up your server correctly
- Dark mode support
- Now you don't need to set up your subscription system in setup wizard
Broadcasting
- Pusher implementation for live communication
- Native websocket server as replacement for Pusher (more details soon)
- Live notification
System
- Database backups on daily basis
Admin & Settings
Dashboard
- New widget to track the latest upload and download was added
- New widget with the latest transactions was added into extended license version
- New earnings widget was added
- New alerts will tell you if you are missing plan or you don't have running cron correctly
Settings / Server
- Ability to see if cron job is running correctly
- Ability to download your server log from admin panel
- Ability to see latest 5 database backups
- Ability to check if writable permission for exact folders are set correctly
- Ability to check if you have correctly set php version and php.ini variables
- Ability to see if you have installed all required php extensions
Settings / Environment
- Ability to set Broadcasting from admin settings
- Ability to set Storage Driver from admin settings
- Ability to set Mail Driver from admin settings
Settings / Appearance
- Ability to change entire VueFileManager color scheme
- Ability to set dark mode logo for main and horizontal logo
- Ability to set your own OG Image
- Ability to set your own Touch Image
Settings / Login & Registration
- New option where you can require email verification was added
- New widgets to set up Facebook, Google and GitHub social authentication
Settings / Application
- New options to set up reCaptcha
Settings / Adsense
- Ability to manage Google Adsense
Dev
- PHP 8 support
- New DDD design for the backend
- Shipped with the latest version of Laravel 9.x
- Passport was replaced by Sanctum
- New artisan command that expressly installs the entire application
- New artisan command that expressly installs the entire application with the demo data
- ~80% Of the frontend code was migrated into Tailwind v3. We will continue to reach 100% tailwind friendly

View File

@@ -233,18 +233,18 @@ return [
'billing_alert_reached_short_note' => 'The billing alert you set previously has been reached. Please revise your spending.',
'billing_alert_reached_long' => 'Your billing alert has been reached!',
'billing_alert_reached_long_note' => 'The billing alert you set previously has been reached. Please go to your user account and revise your spending',
'you_received_bonus' => 'You Received {bonus}',
'you_received_bonus_note' => 'You received credit bonus {bonus} from us. Happy spending!',
'you_received_registration_bonus_note' => 'You received credit bonus {bonus} for your registration. Happy spending!',
'you_received_bonus' => 'You Received :bonus',
'you_received_bonus_note' => 'You received credit bonus :bonus from us. Happy spending!',
'you_received_registration_bonus_note' => 'You received credit bonus :bonus for your registration. Happy spending!',
'withdrawal_failed_short' => 'Withdrawal Failed',
'withdrawal_failed_short_note' => "Your credit withdrawal for your account didn't go through. Please make sure you have sufficient funds on your account.",
'withdrawal_failed_long' => 'Uh-oh! Your credit withdrawal for your pre-paid subscription failed',
'withdrawal_failed_long_note' => "It looks like your subscription credit withdrawal for your account didn't go through. Please make sure you have sufficient funds on your account and we'll give it another try!",
'fund_your_account' => 'Fund Your Account',
'subscription_created_short' => 'Subscription Has Been Created',
'subscription_created_short_note' => 'Your subscription {plan} has been successfully created',
'subscription_created_long' => 'Your subscription {plan} has been successfully created',
'subscription_created_long_note' => 'You have been successfully subscribed to your {plan} subscription. Now you can take full advantage of our platform.',
'subscription_created_short_note' => 'Your subscription :plan has been successfully created',
'subscription_created_long' => 'Your subscription :plan has been successfully created',
'subscription_created_long_note' => 'You have been successfully subscribed to your :plan subscription. Now you can take full advantage of our platform.',
'go_to_subscription' => 'Go to Subscription',
'charge_from_card_failed_subject' => 'Uh-oh! Your withdrawal from your credit card for pre-paid subscription failed',
'charge_from_card_failed_line' => "It looks like withdrawal from your credit card for pre-paid subscription for your account didn't go through. Please check your credit card or register new credit card for your account and we'll give it another try!",
@@ -253,7 +253,7 @@ return [
'charge_from_card_failed_again_line' => "It looks like withdrawal from your credit card for pre-paid subscription for your account didn't go through once again. Please check your credit card or register new credit card for your account and we'll give it another try!",
'charge_from_card_failed_again_action' => 'Update Your Payment Information',
'confirm_payment' => 'Confirm Payment',
'confirm_payment_greeting' => 'Confirm your {amount} payment',
'confirm_payment_greeting' => 'Confirm your :amount payment',
'confirm_payment_line' => 'Extra confirmation is needed to process your payment. Please continue to the payment page by clicking on the button below.',
'confirm_payment_action' => 'Confirm Payment',
'registration_bonus' => 'Registration Bonus',
@@ -263,6 +263,7 @@ return [
'date_of_issue' => 'Date of issue',
'period' => 'Period',
'Description' => 'description',
'description' => 'description',
'generated_by' => 'Generated by',
],
'regular' => [
@@ -270,10 +271,10 @@ return [
'cancel' => 'Cancel',
'close' => 'Close',
'create_folder' => 'Create folder',
'delete' => 'Delete item',
'delete' => 'Delete',
'download_item' => 'Download item',
'info_panel' => 'Info panel',
'move' => 'Move item',
'move' => 'Move',
'print' => 'Print item',
'share_item' => 'Share item',
'sorting_view' => 'Sorting and View',
@@ -760,7 +761,7 @@ return [
'notification_center' => 'Notification Center',
'clear_all' => 'Clear all',
'not_any_notifications' => "There aren't any notifications.",
'unread' => 'unread',
'unread' => 'Unread',
'read' => 'Read',
'notifications' => 'Notifications',
'options' => 'Options',
@@ -904,27 +905,27 @@ return [
'total_x_of_x_members' => 'Total ${use} of ${total} Members',
'go_back_from_x' => 'Go back from {location}',
'new_team_invitation' => 'New Team Invitation',
'x_invite_to_join_team' => "{name} invite you to join into Team Folder.",
'team_invitation_notify_title' => 'You are invited to collaboration with team folder in {app}',
'x_invite_to_join_team' => ':name invite you to join into Team Folder.',
'team_invitation_notify_title' => 'You are invited to collaboration with team folder in :app',
'team_invitation_notify_desc' => 'You are invited to collaboration with team folder',
'team_invitation_notify_desc_without_account' => 'You are invited to collaboration with team folder. But at first, you have to create an account to proceed into team folder.',
'join_into_team_folder' => 'Join into Team Folder',
'join_and_create_account' => 'Join & Create an Account',
'file_request_filled' => 'File Request Filled',
'file_request_filled_desc' => "Your file request for '{name}' folder was filled successfully.",
'file_request_filled_desc' => "Your file request for ':name' folder was filled successfully.",
'show_files' => 'Show Files',
'file_request_filled_mail' => "Your file request was fulfilled in your '{name}' folder",
'file_request_filled_mail_note' => "We are emailing you because your file request was fulfilled. Please click on the link below to show uploaded files.",
'file_request_filled_mail' => "Your file request was fulfilled in your ':name' folder",
'file_request_filled_mail_note' => 'We are emailing you because your file request was fulfilled. Please click on the link below to show uploaded files.',
'thanks_salutation' => 'Thank you for using our application!',
'upload_your_files' => 'Upload your Files',
'file_request_optional_message' => "PS: {name} left you a message: {notes}",
'file_request_notify_title' => '{name} Request You for File Upload',
'file_request_notify_description' => "We are emailing you because {name} requested files from you. Please click on the link below and upload your files for {name}.",
'file_request_optional_message' => 'PS: :name left you a message: :notes',
'file_request_notify_title' => ':name Request You for File Upload',
'file_request_notify_description' => 'We are emailing you because :name requested files from you. Please click on the link below and upload your files for :name.',
'user_action_not_allowed' => 'This user action is not allowed.',
'pcs.' => 'Pcs.',
'mem.' => 'Mem.',
'password_doesnt_match' => 'The provided password does not match your current password.',
'amount' => 'Amount',
'upload_request_default_folder' => 'Upload Request from {timestamp}',
'upload_request_default_folder' => 'Upload Request from :timestamp',
],
];

View File

@@ -1,7 +1,7 @@
<?php
return [
'version' => '2.0.0',
'version' => '2.0.2',
'is_demo' => env('APP_DEMO', false),
@@ -60,4 +60,8 @@ return [
],
],
],
'paginate' => [
'perPage' => 8,
],
];

188
package-lock.json generated
View File

@@ -1231,9 +1231,9 @@
}
},
"@stripe/stripe-js": {
"version": "1.24.0",
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.24.0.tgz",
"integrity": "sha512-8CEILOpzoRhGwvgcf6y+BlPyEq1ZqxAv3gsX7LvokFYvbcyH72GRcHQMGXuZS3s7HqfYQuTSFrvZNL/qdkgA9Q=="
"version": "1.29.0",
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.29.0.tgz",
"integrity": "sha512-OsUxk0VLlum8E2d6onlEdKuQcvLMs7qTrOXCnl/BGV3fAm65qr6h3e1IZ5AX4lgUlPRrzRcddSOA5DvkKKYLvg=="
},
"@trysound/sax": {
"version": "0.2.0",
@@ -2088,17 +2088,50 @@
"dev": true
},
"autoprefixer": {
"version": "10.4.2",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz",
"integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==",
"version": "10.4.7",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz",
"integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==",
"dev": true,
"requires": {
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001297",
"fraction.js": "^4.1.2",
"browserslist": "^4.20.3",
"caniuse-lite": "^1.0.30001335",
"fraction.js": "^4.2.0",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
},
"dependencies": {
"browserslist": {
"version": "4.20.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
"integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001332",
"electron-to-chromium": "^1.4.118",
"escalade": "^3.1.1",
"node-releases": "^2.0.3",
"picocolors": "^1.0.0"
}
},
"caniuse-lite": {
"version": "1.0.30001342",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001342.tgz",
"integrity": "sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA==",
"dev": true
},
"electron-to-chromium": {
"version": "1.4.137",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz",
"integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==",
"dev": true
},
"node-releases": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz",
"integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==",
"dev": true
}
}
},
"aws-sign2": {
@@ -4159,9 +4192,9 @@
"dev": true
},
"fraction.js": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz",
"integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
"dev": true
},
"fresh": {
@@ -4761,9 +4794,9 @@
}
},
"immutable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz",
"integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
"integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==",
"dev": true
},
"import-fresh": {
@@ -5252,9 +5285,9 @@
"dev": true
},
"laravel-echo": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.11.3.tgz",
"integrity": "sha512-VNTnnoF8gK29ovxslnrFDt3xgrKiKKW1kTnKKO1A4kYVj4UCKmNO4x2ehRlfg2UTrG/oggwk95p+S9ftQYjXdw==",
"version": "1.11.7",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.11.7.tgz",
"integrity": "sha512-LhEZp/RbdtdMlhptJyn452+aXfz+A1UW2bhJM7NROgXhnNgj+6P9BkG9JcPCBMernp5TGkOGI6A0NPbkAWYWGg==",
"dev": true
},
"laravel-mix": {
@@ -5980,9 +6013,9 @@
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"dev": true
},
"negotiator": {
@@ -6259,9 +6292,9 @@
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"object-hash": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
"integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"dev": true
},
"object-is": {
@@ -6657,12 +6690,12 @@
}
},
"postcss": {
"version": "8.4.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.8.tgz",
"integrity": "sha512-2tXEqGxrjvAO6U+CJzDL2Fk2kPHTv1jQsYkSoMeOis2SsYaXRO2COxTdQp99cYvif9JTXaAk9lYGc3VhJt7JPQ==",
"version": "8.4.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
"integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
"dev": true,
"requires": {
"nanoid": "^3.3.1",
"nanoid": "^3.3.4",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
}
@@ -7047,9 +7080,9 @@
}
},
"prettier-plugin-tailwindcss": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.8.tgz",
"integrity": "sha512-hwarSBCswAXa+kqYtaAkFr3Vop9o04WOyZs0qo3NyvW8L7f1rif61wRyq0+ArmVThOuRBcJF5hjGXYk86cwemg==",
"version": "0.1.11",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.11.tgz",
"integrity": "sha512-a28+1jvpIZQdZ/W97wOXb6VqI762MKE/TxMMuibMEHhyYsSxQA8Ek30KObd5kJI2HF1ldtSYprFayXJXi3pz8Q==",
"dev": true
},
"pretty-time": {
@@ -7586,9 +7619,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sass": {
"version": "1.49.9",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.49.9.tgz",
"integrity": "sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==",
"version": "1.52.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz",
"integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -8197,62 +8230,34 @@
"integrity": "sha512-X324n9OtpTmOMqEgDUEA/RgLrNfBF/jwJdctaPZDzB3mppxJk7TLIDmOreEDm1Bq4R9LSPu4Epf8VSdovNU+iA=="
},
"tailwindcss": {
"version": "3.0.23",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.23.tgz",
"integrity": "sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==",
"version": "3.0.24",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz",
"integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==",
"dev": true,
"requires": {
"arg": "^5.0.1",
"chalk": "^4.1.2",
"chokidar": "^3.5.3",
"color-name": "^1.1.4",
"cosmiconfig": "^7.0.1",
"detective": "^5.2.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.2.11",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"lilconfig": "^2.0.5",
"normalize-path": "^3.0.0",
"object-hash": "^2.2.0",
"postcss": "^8.4.6",
"object-hash": "^3.0.0",
"picocolors": "^1.0.0",
"postcss": "^8.4.12",
"postcss-js": "^4.0.0",
"postcss-load-config": "^3.1.0",
"postcss-load-config": "^3.1.4",
"postcss-nested": "5.0.6",
"postcss-selector-parser": "^6.0.9",
"postcss-selector-parser": "^6.0.10",
"postcss-value-parser": "^4.2.0",
"quick-lru": "^5.1.1",
"resolve": "^1.22.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
@@ -8268,19 +8273,30 @@
"is-glob": "^4.0.3"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"lilconfig": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
"integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==",
"dev": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"postcss-load-config": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz",
"integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
"lilconfig": "^2.0.5",
"yaml": "^1.10.2"
}
},
"postcss-selector-parser": {
"version": "6.0.10",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
}
}
}
@@ -8597,9 +8613,9 @@
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"v-click-outside": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/v-click-outside/-/v-click-outside-3.1.2.tgz",
"integrity": "sha512-gMdRqfRE6m6XU6SiFi3dyBlFB2MWogiXpof8Aa3LQysrl9pzTndqp/iEaAphLoadaQUFnQ0ec6fLLaxr7LiY6A=="
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/v-click-outside/-/v-click-outside-3.2.0.tgz",
"integrity": "sha512-QD0bDy38SHJXQBjgnllmkI/rbdiwmq9RC+/+pvrFjYJKTn8dtp7Penf9q1lLBta280fYG2q53mgLhQ+3l3z74w=="
},
"validate-npm-package-license": {
"version": "3.0.4",
@@ -8695,9 +8711,9 @@
"integrity": "sha512-W+y2EAI/BxS4Vlcca9scQv8ifeBFck56DRtSwWJ2H4Cw1GLNUYxiZxUHHkuzuI5JPW/cYtL1bPO5xPyEXx4LmQ=="
},
"vue-router": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz",
"integrity": "sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg=="
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.4.tgz",
"integrity": "sha512-x+/DLAJZv2mcQ7glH2oV9ze8uPwcI+H+GgTgTmb5I55bCgY3+vXWIsqbYUzbBSZnwFHEJku4eoaH/x98veyymQ=="
},
"vue-style-loader": {
"version": "4.1.3",

View File

@@ -10,39 +10,39 @@
"production": "mix --production"
},
"devDependencies": {
"autoprefixer": "^10.4.2",
"autoprefixer": "^10.4.7",
"axios": "^0.21.4",
"cross-env": "^5.1",
"laravel-echo": "^1.11.3",
"laravel-echo": "^1.11.7",
"laravel-mix": "^6.0.43",
"postcss": "^8.4.8",
"postcss": "^8.4.14",
"prettier": "^2.5.1",
"prettier-plugin-import-sort": "0.0.7",
"prettier-plugin-tailwindcss": "^0.1.8",
"prettier-plugin-tailwindcss": "^0.1.11",
"pusher-js": "^7.0.6",
"resolve-url-loader": "^2.3.1",
"sass": "^1.49.9",
"sass": "^1.52.1",
"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.24.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.0",
"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.0",
"vue-recaptcha-v3": "^1.9.0",
"vue-router": "^3.5.3",
"vue-router": "^3.5.4",
"vuex": "^3.6.2"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 KiB

After

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 KiB

After

Width:  |  Height:  |  Size: 595 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 KiB

After

Width:  |  Height:  |  Size: 600 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/main.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,75 +1,75 @@
{
"/js/main.js": "/js/main.js",
"/chunks/request.js": "/chunks/request.js?id=deaa7c83da9b78a5",
"/chunks/request-upload.js": "/chunks/request-upload.js?id=2a6d910114ffb8d2",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=3c2fc454c3fce8d2",
"/chunks/status-check.js": "/chunks/status-check.js?id=783c6143db13e6c0",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=c1df85c34d7e9521",
"/chunks/database.js": "/chunks/database.js?id=d4f38bfdef26b0d9",
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=21e576c9c8183e42",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=647bf9cdc907e83c",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=d21b66f2b6e1638e",
"/chunks/shared.js": "/chunks/shared.js?id=d11e0cf1a032ac9d",
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=a9710655d75c8079",
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=c013d98f7386c448",
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=ca8cc89fe5982782",
"/chunks/not-found.js": "/chunks/not-found.js?id=4cb8d3a7a2212c3c",
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=c71981d946a9ca71",
"/chunks/admin.js": "/chunks/admin.js?id=bc5300f72bd1e072",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=d8740b43db79abfe",
"/chunks/invoices.js": "/chunks/invoices.js?id=70fb9a603be2f554",
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=94e96e1bb505ae59",
"/chunks/pages.js": "/chunks/pages.js?id=d1f5d211e9dfc4ae",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=184547a95a64a121",
"/chunks/plans.js": "/chunks/plans.js?id=f6e9d2f34fac6d79",
"/chunks/users.js": "/chunks/users.js?id=651b8af7afecc88e",
"/chunks/user-create.js": "/chunks/user-create.js?id=d24c5037b91a2fa2",
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=20a6ee217157864f",
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=617982724a144a43",
"/chunks/user.js": "/chunks/user.js?id=dae4ac26750f99d0",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=d56437755ba2c6cc",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=c26b370f6f4323fe",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=6d7d1235d1ae5bf2",
"/chunks/user-password.js": "/chunks/user-password.js?id=acd9b49cca55d161",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=47d44b2f8e4e620c",
"/chunks/plan.js": "/chunks/plan.js?id=d8ffa85dc9b68966",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=3010ddb4ba7419e9",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=d3c236e167831f25",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=44ad905bfe1ae983",
"/chunks/payments.js": "/chunks/payments.js?id=051e8246e2b5c9d0",
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=7ec4ad9b9755b2b8",
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=6644b642875c732f",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=692d3291fb9d2cf7",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=27652021b725b9e7",
"/chunks/app-index.js": "/chunks/app-index.js?id=968d5378d871f070",
"/chunks/app-environment.js": "/chunks/app-environment.js?id=09a06687b64b4246",
"/chunks/app-others.js": "/chunks/app-others.js?id=356072b7410b5681",
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=ea65b443a513ad8c",
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=c4c4cda03202a49a",
"/chunks/app-server.js": "/chunks/app-server.js?id=307fce5c9d192bf3",
"/chunks/app-language.js": "/chunks/app-language.js?id=51c79c7bdb8f9382",
"/chunks/homepage.js": "/chunks/homepage.js?id=b45798483b942ac1",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=e110e8923b6ca22f",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=54d3469e6d46cef6",
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=3153532f0d2273c8",
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=d630ed9f6f558509",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=73e0fd17a1b1677d",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=920ebe5b86e59c09",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=9c62b8573fbdd567",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=926b35b6745d99ba",
"/chunks/settings.js": "/chunks/settings.js?id=9e3d5262fd69da2d",
"/chunks/profile.js": "/chunks/profile.js?id=e92af0c70da9aa83",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=080d3133ed6bc14c",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=736118b6409186cc",
"/chunks/billing.js": "/chunks/billing.js?id=e4e8b9c2f7fa6cd2",
"/chunks/platform.js": "/chunks/platform.js?id=65dabf0676a4c674",
"/chunks/files.js": "/chunks/files.js?id=5d6eb9b9f9ecd296",
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=827d3a5dcce159b5",
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=2a4e4e0db02cbcbb",
"/chunks/trash.js": "/chunks/trash.js?id=8362aa0f91231350",
"/chunks/team-folders.js": "/chunks/team-folders.js?id=0a46fecf35a23406",
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=77a33583775c6d8f",
"/chunks/invitation.js": "/chunks/invitation.js?id=64a211c90b505767",
"/chunks/request.js": "/chunks/request.js?id=4dae0cd347eacccf",
"/chunks/request-upload.js": "/chunks/request-upload.js?id=37b9e11f7f085164",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=19a0784e59d768ec",
"/chunks/status-check.js": "/chunks/status-check.js?id=ca27b637120e086a",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=df5bd89528649783",
"/chunks/database.js": "/chunks/database.js?id=6bd9994bd24d6c8d",
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=fc9b6215ce43229b",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=77937d105dfa28ba",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=6dbc3fe81f957a59",
"/chunks/shared.js": "/chunks/shared.js?id=811ed03bd8ff236a",
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=ae81a41ecf6222f9",
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=9ccb8bb19b95a23f",
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=672e931a9fb0b672",
"/chunks/not-found.js": "/chunks/not-found.js?id=9f6ce23ce5d969f1",
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=f564565faa09d6d6",
"/chunks/admin.js": "/chunks/admin.js?id=c48facc21639ee2c",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=c7fa2f0dc8ed949c",
"/chunks/invoices.js": "/chunks/invoices.js?id=1416cbf6d1a593ac",
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=5bf6704f5b599f36",
"/chunks/pages.js": "/chunks/pages.js?id=c8380d571e91e8be",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=b19868b3100360a3",
"/chunks/plans.js": "/chunks/plans.js?id=c8506e0e20966ef7",
"/chunks/users.js": "/chunks/users.js?id=ec687ee365c4248a",
"/chunks/user-create.js": "/chunks/user-create.js?id=bb3b30ce248209f0",
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=a8ffa08ce94ddf4e",
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=3b516dcccbbef20a",
"/chunks/user.js": "/chunks/user.js?id=c191b906a0496fe5",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=80491654e6ee63b1",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=69eb59b682c5482f",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=a69ebc3b23446cda",
"/chunks/user-password.js": "/chunks/user-password.js?id=e1c4ebc07ba426e6",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=82b5180a1d9e1217",
"/chunks/plan.js": "/chunks/plan.js?id=4b267375ea9f19b3",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=a956ceca6865c50c",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=f366690f8764bb20",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=e26d5bd3ecbb4bb1",
"/chunks/payments.js": "/chunks/payments.js?id=dc4586691c25de6f",
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=9942aaac1bdb11e5",
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=717bf97ba2ffdc28",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=55da23af2b076069",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=c308941663208358",
"/chunks/app-index.js": "/chunks/app-index.js?id=aa62aedf1f38cc22",
"/chunks/app-environment.js": "/chunks/app-environment.js?id=538eea914fc27794",
"/chunks/app-others.js": "/chunks/app-others.js?id=3282fb7a70e8e02e",
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=3f8e5f906a4dee4e",
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=4ee8de4ac0dae19e",
"/chunks/app-server.js": "/chunks/app-server.js?id=dd8c15d4646053cd",
"/chunks/app-language.js": "/chunks/app-language.js?id=ba087a47c8efca29",
"/chunks/homepage.js": "/chunks/homepage.js?id=f1cfba4f0152f4b9",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=2504793131107b1f",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=2e0b16655d2d85d7",
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=25b805ade5230382",
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=f4562229776d9f56",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=295d214d04f2a86d",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=77351b7631a6ee6c",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=50a1bc5e4ed86ec9",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=f652de052dba55c1",
"/chunks/settings.js": "/chunks/settings.js?id=f41a95bc12c30010",
"/chunks/profile.js": "/chunks/profile.js?id=5b2ed82815320625",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=c912a79595c2efcb",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=6fec7aac1a5280c7",
"/chunks/billing.js": "/chunks/billing.js?id=3a9b4a3869602995",
"/chunks/platform.js": "/chunks/platform.js?id=b966740835699124",
"/chunks/files.js": "/chunks/files.js?id=4e608db6e46c8e1a",
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=75ae670c0dd88d28",
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=20366862e84678f3",
"/chunks/trash.js": "/chunks/trash.js?id=3930329bfca5ef73",
"/chunks/team-folders.js": "/chunks/team-folders.js?id=bf4c9aa124ec9b8e",
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=87d0fb60c573f01d",
"/chunks/invitation.js": "/chunks/invitation.js?id=9ed8456c9d6d5ce1",
"/css/tailwind.css": "/css/tailwind.css",
"/css/app.css": "/css/app.css"
}

View File

@@ -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"
/>
<!-- Infinite Loader Element -->
<div
v-show="showInfiniteLoadSpinner"
class="relative h-16 md:my-0 my-4"
ref="infinityLoader"
>
<Spinner />
</div>
</div>
</template>
@@ -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')
@@ -83,7 +121,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) {
@@ -133,6 +171,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

View File

@@ -17,7 +17,7 @@
icon="check-square"
:title="$t('selected_multiple')"
:subtitle="clipboard.length + ' ' + $tc('items', clipboard.length)"
v-if="clipboard.length > 1 || !isSelectedItem"
v-if="clipboard.length > 1 && !isSelectedItem"
/>
<TreeMenu

View File

@@ -839,13 +839,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)
}

View File

@@ -235,6 +235,7 @@ const FunctionHelpers = {
formData.set('file', chunk, source_name)
formData.set('path', item.path)
formData.set('parent_id', item.parent_id)
formData.set('extension', item.file.name.split('.').pop())
formData.set('is_last', isLast)
// Upload chunks
@@ -324,19 +325,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) {

View File

@@ -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)) {

View File

@@ -12,93 +12,142 @@ const defaultState = {
isLoading: true,
clipboard: [],
entries: [],
paginate: undefined,
}
const actions = {
getFolder: ({ commit, getters }, id) => {
commit('LOADING_STATE', { loading: true, data: [] })
getFolder: ({ commit, getters },{page, id}) => {
return new Promise ((resolve, reject) => {
axios
.get(`${getters.api}/browse/folders/${id}/${getters.sorting.URI}`)
.then((response) => {
let folders = response.data.folders.data
let files = response.data.files.data
if(!page)
commit('LOADING_STATE', { loading: true, data: [] })
commit('LOADING_STATE', {
loading: false,
data: folders.concat(files),
})
commit('SET_CURRENT_FOLDER', response.data.root)
let currentPage = page || 1
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'),
axios
.get(`${getters.api}/browse/folders/${id}/${getters.sorting.URI}&page=${currentPage}`)
.then((response) => {
commit('SET_PAGINATE', response.data.meta.paginate)
commit('LOADING_STATE', {
loading: false,
data: response.data.data,
})
}
})
},
getRecentUploads: ({ commit, getters }) => {
commit('LOADING_STATE', { loading: true, data: [] })
commit('SET_CURRENT_FOLDER', response.data.meta.root)
axios
.get(getters.api + '/browse/latest')
.then((response) => {
commit('LOADING_STATE', {
loading: false,
data: response.data.files.data,
events.$emit('scrollTop')
resolve(true);
})
commit('SET_CURRENT_FOLDER', undefined)
.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'),
})
}
events.$emit('scrollTop')
})
.catch(() => Vue.prototype.$isSomethingWrong())
},
getMySharedItems: ({ commit, getters }) => {
commit('LOADING_STATE', { loading: true, data: [] })
axios
.get(getters.api + '/browse/share' + getters.sorting.URI)
.then((response) => {
let folders = response.data.folders.data
let files = response.data.files.data
commit('LOADING_STATE', {
loading: false,
data: folders.concat(files),
reject(error)
})
commit('SET_CURRENT_FOLDER', undefined)
events.$emit('scrollTop')
})
.catch(() => Vue.prototype.$isSomethingWrong())
})
},
getTrash: ({ commit, getters }, id) => {
commit('LOADING_STATE', { loading: true, data: [] })
getRecentUploads: ({ commit, getters }, page) => {
return new Promise ((resolve, reject) => {
axios
.get(`${getters.api}/browse/trash/${id}/${getters.sorting.URI}`)
.then((response) => {
let folders = response.data.folders.data
let files = response.data.files.data
if(! page)
commit('LOADING_STATE', { loading: true, data: [] })
let currentPage = page || 1
axios
.get(getters.api + `/browse/latest?page=${currentPage}`)
.then((response) => {
commit('SET_PAGINATE', response.data.meta.paginate)
commit('LOADING_STATE', {
loading: false,
data: response.data.data,
})
commit('SET_CURRENT_FOLDER', undefined)
events.$emit('scrollTop')
commit('LOADING_STATE', {
loading: false,
data: folders.concat(files),
resolve(true)
})
commit('SET_CURRENT_FOLDER', response.data.root)
.catch((error) => {
Vue.prototype.$isSomethingWrong()
events.$emit('scrollTop')
})
.catch(() => Vue.prototype.$isSomethingWrong())
reject(error)
})
})
},
getMySharedItems: ({ commit, getters }, page) => {
return new Promise ((resolve, reject) => {
if(! page)
commit('LOADING_STATE', { loading: true, data: [] })
let currentPage = page || 1
axios
.get(`${getters.api}/browse/share${getters.sorting.URI}&page=${currentPage}`)
.then((response) => {
commit('SET_PAGINATE', response.data.meta.paginate)
commit('LOADING_STATE', {
loading: false,
data: response.data.data,
})
commit('SET_CURRENT_FOLDER', undefined)
events.$emit('scrollTop')
resolve(true)
})
.catch((error) => {
Vue.prototype.$isSomethingWrong()
reject(error)
})
})
},
getTrash: ({ commit, getters },{page, id}) => {
return new Promise ((resolve, reject) => {
if(! page)
commit('LOADING_STATE', { loading: true, data: [] })
let currentPage = page || 1
axios
.get(`${getters.api}/browse/trash/${id}/${getters.sorting.URI}&page=${currentPage}`)
.then((response) => {
commit('SET_PAGINATE', response.data.meta.paginate)
commit('LOADING_STATE', {
loading: false,
data: response.data.data,
})
commit('SET_CURRENT_FOLDER', response.data.meta.root)
events.$emit('scrollTop')
resolve(true)
})
.catch((error) => {
Vue.prototype.$isSomethingWrong()
reject(error)
})
})
},
getFolderTree: ({ commit, getters }) => {
return new Promise((resolve, reject) => {
@@ -116,17 +165,24 @@ const actions = {
commit('UPDATE_FOLDER_TREE', response.data)
})
.catch((error) => {
reject(error)
Vue.prototype.$isSomethingWrong()
reject(error)
})
})
},
}
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) {
@@ -221,6 +277,7 @@ const getters = {
clipboard: (state) => state.clipboard,
isLoading: (state) => state.isLoading,
entries: (state) => state.entries,
paginate: (state) => state.paginate
}
export default {

View File

@@ -20,21 +20,24 @@ const defaultState = {
sharedFile: undefined,
}
const actions = {
getSharedFolder: ({ commit, getters }, id) => {
commit('LOADING_STATE', { loading: true, data: [] })
getSharedFolder: ({ commit, getters }, {page, id}) => {
if(! page)
commit('LOADING_STATE', { loading: true, data: [] })
let currentPage = page || 1
return new Promise((resolve, reject) => {
axios
.get(`/api/browse/folders/${id}/${router.currentRoute.params.token}${getters.sorting.URI}`)
.get(`/api/browse/folders/${id}/${router.currentRoute.params.token}${getters.sorting.URI}&page=${currentPage}`)
.then((response) => {
let folders = response.data.folders.data
let files = response.data.files.data
commit('SET_PAGINATE', response.data.meta.paginate)
commit('LOADING_STATE', {
loading: false,
data: folders.concat(files),
data: response.data.data,
})
commit('SET_CURRENT_FOLDER', response.data.root)
commit('SET_CURRENT_FOLDER', response.data.meta.root)
events.$emit('scrollTop')

View File

@@ -9,89 +9,107 @@ const defaultState = {
}
const actions = {
getTeamFolder: ({ commit, getters }, id) => {
commit('LOADING_STATE', { loading: true, data: [] })
getTeamFolder: ({ commit, getters }, {page, id}) => {
return new Promise ((resolve, reject) => {
if (typeof id === 'undefined') {
commit('SET_CURRENT_TEAM_FOLDER', null)
}
if(! page)
commit('LOADING_STATE', { loading: true, data: [] })
if (typeof id === 'undefined') {
commit('SET_CURRENT_TEAM_FOLDER', null)
}
axios
.get(`${getters.api}/teams/folders/${id}/${getters.sorting.URI}`)
.then((response) => {
let folders = response.data.folders.data
let files = response.data.files.data
let currentPage = page || 1
axios
.get(`${getters.api}/teams/folders/${id}/${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)
if (
!getters.currentTeamFolder ||
getters.currentTeamFolder.data.id !== response.data.teamFolder.data.id
) {
commit('SET_CURRENT_TEAM_FOLDER', response.data.teamFolder)
}
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)
if (
!getters.currentTeamFolder ||
getters.currentTeamFolder.data.id !== response.data.teamFolder.data.id
) {
commit('SET_CURRENT_TEAM_FOLDER', response.data.teamFolder)
}
events.$emit('scrollTop')
resolve(true)
})
.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'),
})
}
reject(error)
})
})
},
getSharedWithMeFolder: ({ commit, getters }, id) => {
commit('LOADING_STATE', { loading: true, data: [] })
getSharedWithMeFolder: ({ commit, getters }, {page, id}) => {
return new Promise ((resolve, reject) => {
if(! page)
commit('LOADING_STATE', { loading: true, data: [] })
if (typeof id === 'undefined') {
commit('SET_CURRENT_TEAM_FOLDER', null)
}
if (typeof id === 'undefined') {
commit('SET_CURRENT_TEAM_FOLDER', null)
}
axios
.get(`${getters.api}/teams/shared-with-me/${id}/${getters.sorting.URI}`)
.then((response) => {
let folders = response.data.folders.data
let files = response.data.files.data
commit('LOADING_STATE', {
loading: false,
data: folders.concat(files),
})
commit('SET_CURRENT_FOLDER', response.data.root)
if (
!getters.currentTeamFolder ||
getters.currentTeamFolder.data.id !== response.data.teamFolder.data.id
) {
commit('SET_CURRENT_TEAM_FOLDER', response.data.teamFolder)
}
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'),
let currentPage = page || 1
axios
.get(`${getters.api}/teams/shared-with-me/${id}/${getters.sorting.URI}&page=${currentPage}`)
.then((response) => {
commit('SET_PAGINATE', response.data.meta.paginate)
commit('LOADING_STATE', {
loading: false,
data: response.data.data,
})
}
})
commit('SET_CURRENT_FOLDER', response.data.meta.root)
if (
!getters.currentTeamFolder ||
getters.currentTeamFolder.data.id !== response.data.teamFolder.data.id
) {
commit('SET_CURRENT_TEAM_FOLDER', response.data.teamFolder)
}
events.$emit('scrollTop')
resolve(true)
})
.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'),
})
}
reject(error)
})
})
},
getTeamFolderTree: ({ commit, getters }) => {
return new Promise((resolve, reject) => {

View File

@@ -15,8 +15,8 @@ const actions = {
axios
.get(`/api/upload-request/${router.currentRoute.params.token}/browse/${id}${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 }) => {

View File

@@ -75,7 +75,7 @@ const actions = {
items.forEach((item) => {
if (item.data.type === 'folder') {
if (
context.getters.user.data.relationships.favourites.data.find((folder) => folder.id === item.data.id)
context.getters.user.data.relationships.favourites.find((folder) => folder.id === item.data.id)
)
return
@@ -92,7 +92,7 @@ const actions = {
// Check is favorites already don't include some of pushed folders
items.map((item) => {
if (!context.getters.user.data.relationships.favourites.data.find((folder) => folder.data.id === item.id)) {
if (!context.getters.user.data.relationships.favourites.find((folder) => folder.data.id === item.id)) {
pushToFavorites.push(item)
}
})
@@ -152,7 +152,7 @@ const mutations = {
},
ADD_TO_FAVOURITES(state, folder) {
folder.forEach((item) => {
state.user.data.relationships.favourites.data.push(item)
state.user.data.relationships.favourites.push(item)
})
},
UPDATE_FIRST_NAME(state, name) {
@@ -169,12 +169,12 @@ const mutations = {
}
},
REMOVE_ITEM_FROM_FAVOURITES(state, item) {
state.user.data.relationships.favourites.data = state.user.data.relationships.favourites.data.filter(
state.user.data.relationships.favourites = state.user.data.relationships.favourites.filter(
(folder) => folder.data.id !== item.data.id
)
},
UPDATE_NAME_IN_FAVOURITES(state, data) {
state.user.data.relationships.favourites.data.find((folder) => {
state.user.data.relationships.favourites.find((folder) => {
if (folder.id === data.id) {
folder.name = data.name
}

View File

@@ -7,6 +7,7 @@
<!--Spotlight Addons-->
<CreateUploadRequestPopup />
<CreateTeamFolderPopup />
<NotificationsPopup />
<!--Mobile Navigation-->
<MobileNavigation />
@@ -84,6 +85,7 @@ import {
import { mapGetters } from 'vuex'
import CreateUploadRequestPopup from "../components/Others/CreateUploadRequestPopup";
import CreateTeamFolderPopup from "../components/Teams/CreateTeamFolderPopup";
import NotificationsPopup from "../components/Others/NotificationsPopup";
export default {
name: 'Admin',
@@ -188,6 +190,7 @@ export default {
},
},
components: {
NotificationsPopup,
CreateTeamFolderPopup,
CreateUploadRequestPopup,
MobileNavigationToolbar,

View File

@@ -185,7 +185,7 @@
</div>
<!-- Subscription -->
<div v-if="app" class="card shadow-card">
<div v-if="app && config.isSaaS" class="card shadow-card">
<FormLabel icon="credit-card">
{{ $t('subscription') }}
</FormLabel>

View File

@@ -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

View File

@@ -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

View File

@@ -251,7 +251,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')
@@ -263,7 +263,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))

View File

@@ -152,7 +152,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')

View File

@@ -228,7 +228,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))

View File

@@ -234,7 +234,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))
@@ -249,7 +249,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', {

View File

@@ -275,7 +275,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')
@@ -287,7 +287,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))

View File

@@ -146,7 +146,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))

View File

@@ -7,6 +7,7 @@
<!--Spotlight Addons-->
<CreateUploadRequestPopup />
<CreateTeamFolderPopup />
<NotificationsPopup />
<ConfirmPopup />
@@ -92,10 +93,12 @@ import MobileNavigationToolbar from '../components/Mobile/MobileNavigationToolba
import CreateUploadRequestPopup from "../components/Others/CreateUploadRequestPopup";
import CreateTeamFolderPopup from "../components/Teams/CreateTeamFolderPopup";
import ChangeSubscriptionPopup from "../components/Subscription/ChangeSubscriptionPopup";
import NotificationsPopup from "../components/Others/NotificationsPopup";
export default {
name: 'Settings',
components: {
NotificationsPopup,
ChangeSubscriptionPopup,
CreateTeamFolderPopup,
CreateUploadRequestPopup,

View File

@@ -105,7 +105,7 @@
chunkSize: {{ format_bytes(config('vuefilemanager.chunk_size')) }},
isAuthenticated: {{ $isUser ? 1 : 0 }},
isSaaS: {{ $settings && optional($settings)->license === 'Extended' ? 1 : 0 }},
isSaaS: {{ $settings && optional($settings)->license === 'extended' ? 1 : 0 }},
isDev: {{ is_dev() ? 1 : 0 }},
isDemo: {{ config('vuefilemanager.is_demo') ? 1 : 0 }},

View File

@@ -1,8 +1,8 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Socialite\Controllers;
use App\Users\Models\User;
@@ -8,15 +7,16 @@ use App\Http\Controllers\Controller;
use Laravel\Socialite\Facades\Socialite;
use App\Users\Actions\CreateNewUserAction;
use Illuminate\Contracts\Auth\StatefulGuard;
use VueFileManager\Subscription\Domain\Plans\Exceptions\MeteredBillingPlanDoesntExist;
use VueFileManager\Subscription\Domain\Plans\Models\Plan;
use VueFileManager\Subscription\Domain\Plans\Exceptions\MeteredBillingPlanDoesntExist;
class SocialiteCallbackController extends Controller
{
public function __construct(
protected StatefulGuard $guard,
protected StatefulGuard $guard,
public CreateNewUserAction $createNewUser,
) {}
) {
}
/**
* @throws MeteredBillingPlanDoesntExist
@@ -60,7 +60,7 @@ class SocialiteCallbackController extends Controller
}
// Check if account registration is enabled
if (!$isAllowedRegistration) {
if (! $isAllowedRegistration) {
return response([
'type' => 'error',
'message' => 'User registration is not allowed',

View File

@@ -1,10 +1,9 @@
<?php
namespace App\Users\Actions;
use App\Users\Rules\PasswordValidationRules;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use App\Users\Rules\PasswordValidationRules;
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
class UpdateUserPassword implements UpdatesUserPasswords
@@ -25,7 +24,7 @@ class UpdateUserPassword implements UpdatesUserPasswords
'current_password' => ['required', 'string'],
'password' => $this->passwordRules(),
])->after(function ($validator) use ($user, $input) {
if (!isset($input['current_password']) || !Hash::check($input['current_password'], $user->password)) {
if (! isset($input['current_password']) || ! Hash::check($input['current_password'], $user->password)) {
$validator->errors()->add('current_password', __t('password_doesnt_match'));
}
})->validateWithBag('updatePassword');

View File

@@ -159,8 +159,7 @@ class User extends Authenticatable implements MustVerifyEmail
->with([
'parent:id,name',
'shared:token,id,item_id,permission,is_protected,expire_in',
])
->take(40);
]);
}
/**

View File

@@ -2,7 +2,6 @@
namespace Domain\Browsing\Controllers;
use Str;
use Illuminate\Http\Request;
use Domain\Files\Models\File;
use Domain\Folders\Models\Folder;
use Illuminate\Support\Facades\Auth;
@@ -13,29 +12,53 @@ use Domain\Folders\Resources\FolderCollection;
class BrowseFolderController
{
public function __invoke(
Request $request,
string $id,
): 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,
],
];
}
}

View File

@@ -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,
],
];
}
}

View File

@@ -1,16 +1,15 @@
<?php
namespace Domain\Browsing\Controllers;
use Illuminate\Http\Request;
use Domain\Files\Models\File;
use Domain\Sharing\Models\Share;
use Domain\Folders\Models\Folder;
use Illuminate\Support\Facades\Auth;
use Domain\Files\Resources\FilesCollection;
use Domain\Folders\Resources\FolderCollection;
class BrowseSharedItemsController
{
public function __invoke(): array
public function __invoke(Request $request): array
{
$user_id = Auth::id();
@@ -36,11 +35,16 @@ class BrowseSharedItemsController
->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,
],
];
}
}

View File

@@ -1,15 +1,14 @@
<?php
namespace Domain\Browsing\Controllers;
use Illuminate\Http\Request;
use Domain\Files\Models\File;
use Domain\Folders\Models\Folder;
use Illuminate\Support\Facades\Auth;
use Domain\Files\Resources\FilesCollection;
use Domain\Folders\Resources\FolderCollection;
class BrowseTrashContentController
{
public function __invoke(string $id): array
public function __invoke(Request $request, string $id): array
{
$user_id = Auth::id();
$root_id = $id === 'undefined' ? null : $id;
@@ -28,44 +27,42 @@ class BrowseTrashContentController
->where('parent_id', $root_id)
->sortable()
->get();
} else {
// Get folders and files
$folders_trashed = Folder::onlyTrashed()
->with(['trashedFolders', 'parent'])
->where('user_id', $user_id)
->get(['parent_id', 'id', 'name']);
// Collect folders and files to single array
return [
'folders' => new FolderCollection($folders),
'files' => new FilesCollection($files),
'root' => $requestedFolder,
];
$folders = Folder::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->whereIn('id', filter_folders_ids($folders_trashed))
->sortable()
->get();
// Get files trashed
$files = File::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->where(function ($query) use ($folders_trashed) {
$query->whereNull('parent_id');
$query->orWhereNotIn('parent_id', array_values(array_unique(recursiveFind($folders_trashed->toArray(), 'id'))));
})
->sortable()
->get();
}
// Get folders and files
$folders_trashed = Folder::onlyTrashed()
->with(['trashedFolders', 'parent'])
->where('user_id', $user_id)
->get(['parent_id', 'id', 'name']);
$folders = Folder::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->whereIn('id', filter_folders_ids($folders_trashed))
->sortable()
->get();
// Get files trashed
$files_trashed = File::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->where(function ($query) use ($folders_trashed) {
$query->whereNull('parent_id');
$query->orWhereNotIn('parent_id', array_values(array_unique(recursiveFind($folders_trashed->toArray(), 'id'))));
})
->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_trashed),
'root' => $requestedFolder,
'data' => $data,
'links' => $links,
'meta' => [
'paginate' => $paginate,
'root' => $requestedFolder,
],
];
}
}

View File

@@ -1,12 +1,11 @@
<?php
namespace Domain\Browsing\Controllers;
use Illuminate\Http\Request;
use Domain\Files\Models\File;
use Domain\Sharing\Models\Share;
use Domain\Folders\Models\Folder;
use Domain\Files\Resources\FilesCollection;
use Domain\Folders\Resources\FolderResource;
use Domain\Folders\Resources\FolderCollection;
use Domain\Sharing\Actions\ProtectShareRecordAction;
use Domain\Sharing\Actions\VerifyAccessToItemAction;
@@ -24,6 +23,7 @@ class VisitorBrowseFolderController
public function __invoke(
string $id,
Share $shared,
Request $request,
): array {
// Check ability to access protected share record
($this->protectShareRecord)($shared);
@@ -48,10 +48,15 @@ class VisitorBrowseFolderController
// Set thumbnail links for public files
$files->map(fn ($file) => $file->setSharedPublicUrl($shared->token));
list($data, $paginate, $links) = groupPaginate($request, $folders, $files);
return [
'folders' => new FolderCollection($folders),
'files' => new FilesCollection($files),
'root' => new FolderResource($requestedFolder),
'data' => $data,
'links' => $links,
'meta' => [
'paginate' => $paginate,
'root' => new FolderResource($requestedFolder),
],
];
}
}

View File

@@ -19,7 +19,6 @@ class GenerateImageThumbnailAction
collect(config("vuefilemanager.image_sizes.$execution"))
->each(function ($size) use ($userId, $fileName, $imageWidth) {
if ($imageWidth > $size['size']) {
// Create intervention image
$intervention = Image::make(
Storage::disk('local')->path("temp/$userId/$fileName")

View File

@@ -36,9 +36,6 @@ class UploadFileAction
$chunkName = $file->getClientOriginalName();
// File name
$fileName = Str::uuid() . '.' . $file->extension();
// File Path
$filePath = Storage::disk('local')->path('chunks/' . $chunkName);
@@ -60,6 +57,9 @@ class UploadFileAction
if ($request->boolean('is_last')) {
$disk_local = Storage::disk('local');
// File name
$fileName = Str::uuid() . '.' . $request->input('extension');
// Get user data
$user = $userId ? User::find($userId) : Auth::user();

View File

@@ -2,7 +2,6 @@
namespace Domain\Files\Controllers;
use Domain\Files\Models\File;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Domain\Files\Requests\UploadRequest;
use Domain\Files\Resources\FileResource;
@@ -21,15 +20,18 @@ class UploadFileController extends Controller
/**
* Upload file for authenticated master|editor user
*/
public function __invoke(
UploadRequest $request,
): Response | array {
public function __invoke(UploadRequest $request)
{
if (is_demo_account()) {
return ($this->fakeUploadFile)($request);
}
try {
// Upload and store file record
if (! $request->boolean('is_last')) {
return ($this->uploadFiles)($request);
}
$file = ($this->uploadFiles)($request);
return response(new FileResource($file), 201);

View File

@@ -28,6 +28,7 @@ class UploadRequest extends FormRequest
'parent_id' => 'nullable|uuid',
'path' => 'required|string',
'is_last' => 'sometimes|string',
'extension' => 'sometimes|string|nullable',
'file' => ['required', 'file', new DisabledMimetypes],
];
}

View File

@@ -1,16 +1,15 @@
<?php
namespace Domain\Files\Resources;
use Illuminate\Support\Collection;
use Illuminate\Http\Resources\Json\ResourceCollection;
class FilesCollection extends ResourceCollection
{
public $collects = FileResource::class;
public function toArray($request): array
public function toArray($request): Collection
{
return [
'data' => $this->collection,
];
return $this->collection;
}
}

View File

@@ -1,16 +1,15 @@
<?php
namespace Domain\Folders\Resources;
use Illuminate\Support\Collection;
use Illuminate\Http\Resources\Json\ResourceCollection;
class FolderCollection extends ResourceCollection
{
public $collects = FolderResource::class;
public function toArray($request): array
public function toArray($request): Collection
{
return [
'data' => $this->collection,
];
return $this->collection;
}
}

View File

@@ -1,10 +1,10 @@
<?php
namespace Domain\Items\Controllers;
use App\Http\Controllers\Controller;
use Domain\Files\Models\File;
use Domain\Files\Resources\FileResource;
use Domain\Folders\Models\Folder;
use App\Http\Controllers\Controller;
use Domain\Files\Resources\FileResource;
use Domain\Folders\Resources\FolderResource;
use Domain\Items\Requests\RenameItemRequest;
use Domain\Items\Actions\RenameFileOrFolderAction;

View File

@@ -3,7 +3,6 @@ namespace Domain\SetupWizard\Controllers;
use Artisan;
use App\Users\Models\User;
use Domain\SetupWizard\Actions\CreateDiskDirectoriesAction;
use Illuminate\Http\Response;
use Domain\Settings\Models\Setting;
use App\Http\Controllers\Controller;
@@ -12,6 +11,7 @@ use Domain\Pages\Actions\SeedDefaultPagesAction;
use Domain\Settings\Actions\SeedDefaultSettingsAction;
use Domain\SetupWizard\Requests\StoreAdminAccountRequest;
use Domain\Localization\Actions\SeedDefaultLanguageAction;
use Domain\SetupWizard\Actions\CreateDiskDirectoriesAction;
/**
* Create and login admin account

View File

@@ -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,
],
];
}
}

View File

@@ -2,6 +2,7 @@
namespace Domain\Teams\Controllers;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Domain\Files\Models\File;
use Illuminate\Http\Response;
use Domain\Folders\Models\Folder;
@@ -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 Illuminate\Contracts\Routing\ResponseFactory;
use Domain\Teams\Requests\CreateTeamFolderRequest;
@@ -29,7 +28,7 @@ class TeamFoldersController extends Controller
) {
}
public function show($id): array
public function show(Request $request, $id): array
{
$id = Str::isUuid($id) ? $id : null;
@@ -52,12 +51,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,
],
];
}

View File

@@ -61,7 +61,7 @@ class InvitationIntoTeamFolder extends Notification implements ShouldQueue
return [
'category' => 'team-invitation',
'title' => __t('new_team_invitation'),
'description' => __t('x_invite_to_join_team', ['name' => $this->invitation->inviter->settings->name,]),
'description' => __t('x_invite_to_join_team', ['name' => $this->invitation->inviter->settings->name, ]),
'action' => [
'type' => 'invitation',
'params' => [

View File

@@ -1,5 +1,4 @@
<?php
namespace Domain\UploadRequest\Notifications;
use Illuminate\Bus\Queueable;
@@ -19,7 +18,8 @@ class UploadRequestFulfilledNotification extends Notification implements ShouldQ
*/
public function __construct(
public UploadRequest $uploadRequest
) {}
) {
}
/**
* Get the notification's delivery channels.
@@ -50,7 +50,7 @@ class UploadRequestFulfilledNotification extends Notification implements ShouldQ
return [
'category' => 'file-request',
'title' => __t('file_request_filled'),
'description' => __t('file_request_filled_desc', ['name' => $this->uploadRequest->parent->name,]),
'description' => __t('file_request_filled_desc', ['name' => $this->uploadRequest->parent->name, ]),
'action' => [
'type' => 'route',
'params' => [

View File

@@ -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;
@@ -1148,4 +1149,93 @@ if (! function_exists('replace_occurrence')) {
return "{$degrees}°$minutes'$seconds\"$ref";
}
}
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];
}
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace Tests\App\Users;
use Storage;

View File

@@ -133,7 +133,7 @@ class AdminLanguageTranslatorTest extends TestCase
->assertStatus(200)
->assertJsonFragment([
'locale' => 'en',
'close' => 'Close',
'close' => 'Close',
]);
}
@@ -180,7 +180,7 @@ class AdminLanguageTranslatorTest extends TestCase
->getJson("/api/admin/languages/$language->id")
->assertStatus(200)
->assertJsonFragment([
'close' => 'Close',
'close' => 'Close',
'locale' => 'en',
]);
}

View File

@@ -61,21 +61,21 @@ class SetupWizardTest extends TestCase
Setting::all()->each->delete();
$this->postJson('/api/setup/app-setup', [
'color' => '#00BC72',
'title' => 'VueFileManager',
'description' => 'The best file manager on the internet',
'googleAnalytics' => 'UA-12345678-1',
'contactMail' => 'john@doe.com',
'subscriptionType' => 'metered',
'userVerification' => 1,
'userRegistration' => 1,
'storageLimitation' => 1,
'defaultStorage' => 10,
'logo' => UploadedFile::fake()->image('fake-logo.jpg'),
'color' => '#00BC72',
'title' => 'VueFileManager',
'description' => 'The best file manager on the internet',
'googleAnalytics' => 'UA-12345678-1',
'contactMail' => 'john@doe.com',
'subscriptionType' => 'metered',
'userVerification' => 1,
'userRegistration' => 1,
'storageLimitation' => 1,
'defaultStorage' => 10,
'logo' => UploadedFile::fake()->image('fake-logo.jpg'),
'logo_dark' => UploadedFile::fake()->image('fake-logo-dark.jpg'),
'logo_horizontal' => UploadedFile::fake()->image('fake-logo-horizontal.jpg'),
'logo_horizontal' => UploadedFile::fake()->image('fake-logo-horizontal.jpg'),
'logo_horizontal_dark' => UploadedFile::fake()->image('fake-logo-horizontal-dark.jpg'),
'favicon' => UploadedFile::fake()->image('fake-favicon.jpg'),
'favicon' => UploadedFile::fake()->image('fake-favicon.jpg'),
])->assertStatus(204);
$this

View File

@@ -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'));
}
}