Compare commits

..

38 Commits

Author SHA1 Message Date
Peter Papp
83a951b3af cache bursting support in webpack.mix.js 2020-08-31 08:22:51 +02:00
Peter Papp
6762ed25dc frontend build 2020-08-30 15:33:52 +02:00
Peter Papp
6ba869234e FileFullPreview functionality in file grid view 2020-08-30 15:33:20 +02:00
Peter Papp
2c04376a61 v1.7.10 2020-08-30 11:18:28 +02:00
Peter Papp
f180f1fff8 expand tap area for FilePreviewActions.vue arrows 2020-08-30 11:15:51 +02:00
Peter Papp
ab65ca7a13 hide subscription, payment cards and invoices in profile menu when is 'Allow subscription payment' option disabled
frontend build
2020-08-30 11:05:08 +02:00
Peter Papp
8895b5062a small design improves 2020-08-30 09:01:00 +02:00
Peter Papp
2f4aafb1b3 frontend build 2020-08-28 16:17:53 +02:00
Peter Papp
be08c8487a Merge remote-tracking branch 'origin/master' into filepreview
# Conflicts:
#	.env.example
#	package-lock.json
#	package.json
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/App.vue
#	resources/js/helpers.js
#	resources/js/i18n/lang/en.json
#	resources/js/i18n/lang/sk.json
#	resources/js/store/modules/fileFunctions.js
#	resources/js/views/Shared/SharedPage.vue
2020-08-28 16:14:28 +02:00
Peter Papp
0d5df91d2d frontend build 2020-08-27 14:48:48 +02:00
Peter Papp
72e4067beb logo fix in shared page
Renamed option title in share popup
2020-08-27 14:46:07 +02:00
Peter Papp
ba4f888826 Updated README.md and dark mode logo in Dashboard.vue page 2020-08-27 08:25:08 +02:00
Miloš Holba
82b43eb996 FilePreview solved v0.3 issues 2020-08-26 22:37:33 +02:00
Peter Papp
777132ec40 dark mode expiration buttons fix 2020-08-26 18:30:10 +02:00
Peter Papp
7f6f60227a Ability to set expiration for shared link
If user is logged in, after visit SignIn page will be redirected to files page
2020-08-26 08:17:49 +02:00
Peter Papp
ab6ff5dbfd force migration
added maintenance mode
2020-08-26 07:51:16 +02:00
Peter Papp
0d272bc9b7 version change 2020-08-26 07:30:48 +02:00
Peter Papp
2b08d7801b Shared link expiration backend
Redirect from sign in page when user is logged
Updated README.md
2020-08-26 07:29:28 +02:00
Peter Papp
cec4ff6cda shared link title fix 2020-08-25 15:33:16 +02:00
Peter Papp
6f300ba1d5 Link expiration frontend 2020-08-25 15:25:18 +02:00
Peter Papp
86813629ed updated readme 2020-08-25 12:53:46 +02:00
Peter Papp
73a728e606 change vuefilemanager version 2020-08-25 12:37:09 +02:00
Peter Papp
af1228e363 reading metadata in shared link RC 2020-08-25 12:36:21 +02:00
Peter Papp
f3a2758bcc reading metadata in shared link v0.1 2020-08-25 12:04:13 +02:00
Peter Papp
6f9f2f2d34 reading metadata in shared link 2020-08-25 11:03:53 +02:00
Peter Papp
9f4c21a1b1 UserSubscription page fix
PaymentMethods page fix
2020-08-24 09:30:38 +02:00
Miloš Holba
aac0aa755f fix arrow function when is just one file in MediaPreview 2020-08-22 17:55:03 +02:00
Miloš Holba
4be77c07ac remove addEventListener change the video sizing wrapper 2020-08-22 14:18:57 +02:00
Miloš Holba
9372906a3e open to click at audio for mobile 2020-08-22 12:19:23 +02:00
Miloš Holba
e12e521622 add audio mimetypes : mp4, flac 2020-08-21 17:32:36 +02:00
Miloš Holba
0082c3a6a8 change arrows position 2020-08-20 20:31:47 +02:00
Miloš Holba
f79973e922 Fix issues from FilePreview v0.2 2020-08-20 18:50:07 +02:00
Miloš Holba
59ca45e9b1 update filePreview ContextMenu 2020-08-18 19:22:54 +02:00
Miloš Holba
bb22ec1e88 key binds fix 2020-08-17 20:10:30 +02:00
Miloš Holba
ba315014fa split code to components, add arrow functions 2020-08-15 17:41:46 +02:00
Miloš Holba
8387f56048 Move item from gallery fix 2020-08-10 10:30:54 +02:00
Miloš Holba
68acf5f986 Add Gallery 2020-08-08 21:53:43 +02:00
Miloš Holba
785dade6b2 Add Gallery 2020-08-08 21:46:56 +02:00
135 changed files with 7856 additions and 6683 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/app/Console/Commands/SetupDevelopmentEnvironment.php
/node_modules
/public/hot
/public/storage
@@ -11,8 +12,10 @@
.env.backup
.phpunit.result.cache
.phpstorm.meta.php
.vscode/
_ide_helper.php
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
prettier.json

File diff suppressed because it is too large Load Diff

View File

@@ -18,13 +18,13 @@ But, it can't be done without you, development is more and more complicated and
- [Installation](#installation)
- [PHP Configuration](#php-configuration)
- [Chunk Upload](#chunk-upload)
- [Upgrade Guide](#upgrade-guide)
- [Common Instructions](#common-instructions)
- [Update from 1.7.8 to 1.7.9](#update-from-178-to-179)
- [Update from 1.7.x to 1.7.8](#update-from-17x-to-178)
- [Update from 1.6.x to 1.7](#update-from-16x-to-17)
- [Nginx Configuration](#nginx-configuration)
- [Apache Configuration](#apache-configuration)
- [Recover Failed Installation](#installation-failed)
- [Update Guide](#update-guide)
- [Instructions](#instructions)
- [Update from 1.7.x to 1.7.7](#update-from-17x-to-177)
- [Update from 1.6.x to 1.7](#update-from-16x-to-17)
- [Payments](#payments)
- [Get your active plans](#get-your-active-plans)
- [Manage Failed Payments](#manage-failed-payments)
@@ -70,7 +70,7 @@ But, it can't be done without you, development is more and more complicated and
## Installation
#### 1. Upload files on your server
Copy project files to web root folder of your domain. It's mostly located in `html`, `www` or `public_html` folder name.
Upload project files to web root folder of your domain. It's mostly located in `html`, `www` or `public_html` folder name.
#### 2. Configure your web root folder
Configure your web server's document root to point to the public directory of the files you previously uploaded. For example, if you've uploaded the files in `html` folder, your domain root directory should be changed to `html/project_files/public` folder or anything else where domain root is in project `/public` directory.
@@ -104,6 +104,13 @@ At first step you have to verify your purchase code. **Subscription service with
That was the hardest part of installation proces. Please follow instructions in every step of Setup Wizard to successfully install VueFileManager.
#### 7. Set up Cron
Add the following Cron entry to your server. Just update your php path (if it's different) and project path:
```
* * * * * /usr/local/bin/php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
```
## PHP Configuration
There are several PHP settings good to know to setup before you try upload any file. Please set these values in your php.ini, we provide minimal setup for you. When you set `-1` then you set infinity limits.
@@ -116,10 +123,44 @@ max_execution_time = 3600
```
## Chunk & Multipart Upload
VueFileManager in default supporting chunk upload. Default chunk upload size is `128MB`. If you wish change this default value, go to `/config/vuefilemanager.php` and change `chunk_size` attribute.
VueFileManager in default supporting chunk upload. Default chunk upload size is `128MB`. If you wish change this default value, go to your `.env` and change `CHUNK_SIZE` attribute.
When you use external storage, and upload large files, to prevent failing upload process make sure you have enough space in your application space and set higher `max_execution_time` in your php.ini to move your files to external storage.
## Upgrade Guide
### Common Instructions
`Don't forget create backup of your database before make any changes in your production application. If you serve your files in local storage driver pay attention and don't delete your /storage folder!`
These instructions is applicable for all updates. Please follow this step:
- Just rewrite all project files with new excluded `/.env` file and `/storage` folder. These items must be preserved!
### Update from 1.7.8 to 1.7.9
After rewrited old files with new files, log in as admin to the app and go to `your-domain.com/service/upgrade-database`. This will upgrade your database on the background.
Add the following Cron entry to your server. Just update your php path (if it's different) and project path:
```
* * * * * /usr/local/bin/php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
```
### Update from 1.7.x to 1.7.8
For those who have installed VueFileManager via git or any other repository synchronization tool, dont't forget after updated code run `composer update` command to update your vendors.
### Update from 1.6.x to 1.7
For those, who purchase extended licence, place these lines at the end of your `/.env` file:
```
CASHIER_LOGGER=stack
CASHIER_CURRENCY=
STRIPE_KEY=
STRIPE_SECRET=
STRIPE_WEBHOOK_SECRET=
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
```
Then go to https://your-domain.com/upgrade and follow the setup wizard instructions.
## Nginx Configuration
If you running VueFileManager undex Nginx, don't forget set this value in your `nginx.conf` file:
@@ -182,44 +223,6 @@ Make sure you have enabled mod_rewrite. There is an example config for running V
</VirtualHost>
```
## Installation Failed
What to do when installation fail and you can't continue, at first, try to fix issue why installation fail. Probably missing PHP extension or permissions wasn't set correctly.
At worst scenarios, to reset Setup Wizard, delete all tables in your previously created database, delete content of `/storage/framework/cache`. Then replace content in your `.env` file from `.env.example` file.
After these steps, installation will be reseted.
## Update Guide
### Instructions
`Don't forget create backup of your database and storage before make any changes in your production application.`
`If you serve your files in local storage driver pay attention and don't delete your /storage folder`
Follow this steps:
- Make a backup of the .env config file located on your server.
- Upload and replace all the files on your server with what's inside the app folder.
- Restore your `.env` config file on your server.
## Update from 1.7.x to 1.7.7
If you are upgrading app to 1.7.7 from 1.7.x, make sure you have copied new /vendor folder or if you are using terminal or git, run `composer update` command to update your vendors.
## Update from 1.6.x to 1.7
For those, who purchase extended licence, place these lines at the end of your `/.env` file:
```
CASHIER_LOGGER=stack
CASHIER_CURRENCY=
STRIPE_KEY=
STRIPE_SECRET=
STRIPE_WEBHOOK_SECRET=
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
```
Then go to https://your-domain.com/upgrade and follow the setup wizard instructions.
# Payments
VueFileManager is packed with **Stripe** payment options. To configure Stripe, you will be asked in Setup Wizard to set up. Or, if you skip this installation process, you will find stripe set up in you admin `Dashboard / Settings / Payments`.

File diff suppressed because it is too large Load Diff

View File

@@ -3,9 +3,12 @@
namespace App\Console;
use App\Console\Commands\Deploy;
//use App\Console\Commands\SetupDevelopmentEnvironment;
use App\Console\Commands\SetupDevEnvironment;
use App\Console\Commands\SetupProductionEnvironment;
use App\Console\Commands\UpgradeApp;
use App\Share;
use Carbon\Carbon;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@@ -18,18 +21,20 @@ class Kernel extends ConsoleKernel
*/
protected $commands = [
Deploy::class,
//SetupDevelopmentEnvironment::class,
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
$schedule->call(function () {
$this->delete_expired_shared_links();
})->hourly();
}
/**
@@ -39,8 +44,28 @@ class Kernel extends ConsoleKernel
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
/**
* Get and delete expired shared links
*/
protected function delete_expired_shared_links(): void
{
// Get all shares with expiration time
$shares = Share::whereNotNull('expire_in')->get();
$shares->each(function ($share) {
// Get dates
$created_at = Carbon::parse($share->created_at);
// If time was over, then delete share record
if ($created_at->diffInHours(Carbon::now()) >= $share->expire_in) {
$share->delete();
}
});
}
}

View File

@@ -85,8 +85,8 @@ class UserController extends Controller
{
$user = User::find($id);
if (! $user->stripeId()) {
return response('User is not stripe customer', 404);
if (! $user->stripeId() || ! $user->subscription('main')) {
return response('User doesn\'t have any subscription.', 404);
}
return new UserSubscription(

View File

@@ -3,12 +3,15 @@
namespace App\Http\Controllers;
use App\Content;
use App\FileManagerFile;
use App\FileManagerFolder;
use App\Http\Requests\PublicPages\SendMessageRequest;
use App\Http\Resources\PageResource;
use App\Http\Tools\Demo;
use App\Mail\SendSupportForm;
use App\Page;
use App\Setting;
use App\User;
use Artisan;
use Doctrine\DBAL\Driver\PDOException;
use Illuminate\Http\Request;
@@ -96,6 +99,68 @@ class AppFunctionsController extends Controller
->with('installation', $connection);
}
/**
* Get og site for web crawlers
*
* @param $token
*/
public function og_site($token)
{
// Get all settings
$settings = Setting::all();
// Get shared token
$shared = get_shared($token);
// Get user
$user = User::findOrFail($shared->user_id);
// Handle single file
if ($shared->type === 'file') {
// Get file record
$file = FileManagerFile::where('user_id', $shared->user_id)
->where('unique_id', $shared->item_id)
->first();
if ($file->thumbnail) {
$file->setPublicUrl($token);
}
$metadata = [
'is_protected' => $shared->protected,
'url' => url('/shared', ['token' => $token]),
'user' => $user->name,
'name' => $file->name,
'size' => $file->filesize,
'thumbnail' => $file->thumbnail ? $file->thumbnail : null,
];
}
// Handle single file
if ($shared->type === 'folder') {
// Get file record
$folder = FileManagerFolder::where('user_id', $shared->user_id)
->where('unique_id', $shared->item_id)
->first();
$metadata = [
'is_protected' => $shared->protected,
'url' => url('/shared', ['token' => $token]),
'user' => $user->name,
'name' => $folder->name,
'size' => $folder->items,
'thumbnail' => null,
];
}
// Return view
return view("og-view")
->with('settings', json_decode($settings->pluck('value', 'name')->toJson()))
->with('metadata', $metadata);
}
/**
* Check if setup wizard was passed
*

View File

@@ -101,7 +101,7 @@ class FileAccessController extends Controller
$shared = get_shared($token);
// Abort if shared is protected
if ((int) $shared->protected) {
if ((int)$shared->protected) {
abort(403, "Sorry, you don't have permission");
}
@@ -154,7 +154,7 @@ class FileAccessController extends Controller
$shared = get_shared($token);
// Abort if thumbnail is protected
if ((int) $shared->protected) {
if ((int)$shared->protected) {
abort(403, "Sorry, you don't have permission");
}

View File

@@ -69,12 +69,12 @@ class BrowseController extends Controller
->pluck('item_id');
// Get folders and files
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected'])
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->whereIn('unique_id', $folder_ids)
->get();
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected'])
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->whereIn('unique_id', $file_ids)
->get();
@@ -145,13 +145,13 @@ class BrowseController extends Controller
}
// Get folders and files
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected'])
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->where('parent_id', $unique_id)
->orderBy('created_at', 'DESC')
->get();
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected'])
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->where('folder_id', $unique_id)
->orderBy('created_at', 'DESC')
@@ -217,7 +217,7 @@ class BrowseController extends Controller
// Get user id
$user_id = Auth::id();
return FileManagerFile::with(['shared:token,id,item_id,permission,protected'])
return FileManagerFile::with(['shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->where('unique_id', $unique_id)
->firstOrFail();

View File

@@ -51,6 +51,7 @@ class ShareController extends Controller
'protected' => $request->isPassword,
'permission' => $request->permission,
'item_id' => $request->unique_id,
'expire_in' => $request->expiration,
'user_id' => Auth::id(),
'token' => $token,
];
@@ -77,6 +78,7 @@ class ShareController extends Controller
$shared->update([
'permission' => $request->permission,
'protected' => $request->protected,
'expire_in' => $request->expiration,
'password' => $request->password ? Hash::make($request->password) : $shared->password,
]);

View File

@@ -7,6 +7,7 @@ use App\Page;
use App\Setting;
use Artisan;
use Illuminate\Http\Request;
use Schema;
class UpgradeAppController extends Controller
{
@@ -123,4 +124,52 @@ class UpgradeAppController extends Controller
return response('Done', 200);
}
/**
* Start maintenance mode
*/
public function up() {
$command = Artisan::call('up');
if ($command === 0) {
echo 'System is in production mode';
}
}
/**
* End maintenance mode
*/
public function down() {
$command = Artisan::call('down');
if ($command === 0) {
echo 'System is in maintenance mode';
}
}
/**
* Upgrade database
*/
public function upgrade_database()
{
/*
* Upgrade expire_in in shares table
*
* @since v1.7.9
*/
if (! Schema::hasColumn('shares', 'expire_in')) {
$command = Artisan::call('migrate', [
'--force' => true
]);
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
}
}
}

View File

@@ -12,6 +12,8 @@ class CheckForMaintenanceMode extends Middleware
* @var array
*/
protected $except = [
//
'/service/upgrade-database',
'/service/down',
'/service/up',
];
}

View File

@@ -28,6 +28,7 @@ class CreateShareRequest extends FormRequest
'isPassword' => 'required|boolean',
'unique_id' => 'required|integer',
'type' => 'required|string',
'expiration' => 'integer|nullable',
'permission' => 'string',
'password' => 'string',
];

View File

@@ -27,6 +27,7 @@ class UpdateShareRequest extends FormRequest
return [
'protected' => 'required|boolean',
'permission' => 'nullable|string',
'expiration' => 'integer|nullable',
'password' => 'string',
];
}

View File

@@ -22,6 +22,7 @@ class ShareResource extends JsonResource
'permission' => $this->permission,
'protected' => (int) $this->protected,
'item_id' => (int) $this->item_id,
'expire_in' => (int) $this->expire_in,
'token' => $this->token,
'link' => $this->link,
'type' => $this->type,

View File

@@ -5,6 +5,25 @@ namespace App;
use Illuminate\Database\Eloquent\Model;
use Kyslik\ColumnSortable\Sortable;
/**
* App\Page
*
* @property int $id
* @property int $visibility
* @property string $title
* @property string $slug
* @property string $content
* @method static \Illuminate\Database\Eloquent\Builder|Page newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Page newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Page query()
* @method static \Illuminate\Database\Eloquent\Builder|Page sortable($defaultParameters = null)
* @method static \Illuminate\Database\Eloquent\Builder|Page whereContent($value)
* @method static \Illuminate\Database\Eloquent\Builder|Page whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Page whereSlug($value)
* @method static \Illuminate\Database\Eloquent\Builder|Page whereTitle($value)
* @method static \Illuminate\Database\Eloquent\Builder|Page whereVisibility($value)
* @mixin \Eloquent
*/
class Page extends Model
{
use Sortable;

View File

@@ -4,6 +4,20 @@ namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* App\Setting
*
* @property int $id
* @property string $name
* @property string|null $value
* @method static \Illuminate\Database\Eloquent\Builder|Setting newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Setting newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Setting query()
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereValue($value)
* @mixin \Eloquent
*/
class Setting extends Model
{
public $timestamps = false;

View File

@@ -73,6 +73,7 @@ use Rinvex\Subscriptions\Traits\HasSubscriptions;
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRole($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereStripeId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereTrialEndsAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User sortable($defaultParameters = null)
*/
class User extends Authenticatable
{
@@ -193,7 +194,7 @@ class User extends Authenticatable
*/
public function getFolderTreeAttribute()
{
return FileManagerFolder::with(['folders.shared', 'shared:token,id,item_id,permission,protected'])
return FileManagerFolder::with(['folders.shared', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('parent_id', 0)
->where('user_id', $this->id)
->get();
@@ -258,7 +259,7 @@ class User extends Authenticatable
*/
public function favourite_folders()
{
return $this->belongsToMany(FileManagerFolder::class, 'favourite_folder', 'user_id', 'folder_unique_id', 'id', 'unique_id')->with('shared:token,id,item_id,permission,protected');
return $this->belongsToMany(FileManagerFolder::class, 'favourite_folder', 'user_id', 'folder_unique_id', 'id', 'unique_id')->with('shared:token,id,item_id,permission,protected,expire_in');
}
/**

View File

@@ -4,6 +4,34 @@ namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* App\UserSettings
*
* @property int $id
* @property int $user_id
* @property int $storage_capacity
* @property string|null $billing_name
* @property string|null $billing_address
* @property string|null $billing_state
* @property string|null $billing_city
* @property string|null $billing_postal_code
* @property string|null $billing_country
* @property string|null $billing_phone_number
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings query()
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingAddress($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingCity($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingCountry($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingName($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingPhoneNumber($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingPostalCode($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingState($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereStorageCapacity($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereUserId($value)
* @mixin \Eloquent
*/
class UserSettings extends Model
{
public $timestamps = false;

View File

@@ -15,6 +15,7 @@
"fruitcake/laravel-cors": "^1.0",
"gabrielelana/byte-units": "^0.5.0",
"intervention/image": "^2.5",
"jaybizzle/laravel-crawler-detect": "^1.2",
"kyslik/column-sortable": "^6.3",
"laravel/cashier": "^12.0",
"laravel/framework": "^7.0",

115
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "0d1b10acc2a996969b828cc7f51cdee6",
"content-hash": "aadbe31a952d26aab5730369e2bf4089",
"packages": [
{
"name": "asm89/stack-cors",
@@ -1467,6 +1467,119 @@
],
"time": "2019-11-02T09:15:47+00:00"
},
{
"name": "jaybizzle/crawler-detect",
"version": "v1.2.98",
"source": {
"type": "git",
"url": "https://github.com/JayBizzle/Crawler-Detect.git",
"reference": "02b24e5d4dc347737577f48c688ee14c3b5dfd4f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/02b24e5d4dc347737577f48c688ee14c3b5dfd4f",
"reference": "02b24e5d4dc347737577f48c688ee14c3b5dfd4f",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8|^5.5|^6.5",
"satooshi/php-coveralls": "1.*"
},
"type": "library",
"autoload": {
"psr-4": {
"Jaybizzle\\CrawlerDetect\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Beech",
"email": "m@rkbee.ch",
"role": "Developer"
}
],
"description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent",
"homepage": "https://github.com/JayBizzle/Crawler-Detect/",
"keywords": [
"crawler",
"crawler detect",
"crawler detector",
"crawlerdetect",
"php crawler detect"
],
"time": "2020-08-20T18:36:15+00:00"
},
{
"name": "jaybizzle/laravel-crawler-detect",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/JayBizzle/Laravel-Crawler-Detect.git",
"reference": "e39b536fb5e4f21a49328e83a2ab26f0b64b06f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JayBizzle/Laravel-Crawler-Detect/zipball/e39b536fb5e4f21a49328e83a2ab26f0b64b06f7",
"reference": "e39b536fb5e4f21a49328e83a2ab26f0b64b06f7",
"shasum": ""
},
"require": {
"jaybizzle/crawler-detect": "1.*",
"php": ">=5.4.0"
},
"require-dev": {
"orchestra/testbench": "3.1.*",
"phpunit/phpunit": "4.*"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Jaybizzle\\LaravelCrawlerDetect\\LaravelCrawlerDetectServiceProvider"
],
"aliases": {
"Crawler": "Jaybizzle\\LaravelCrawlerDetect\\Facades\\LaravelCrawlerDetect"
}
}
},
"autoload": {
"psr-4": {
"Jaybizzle\\LaravelCrawlerDetect\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Beech",
"email": "mbeech@mark-beech.co.uk"
}
],
"description": "A Laravel package to detect web crawlers via the user agent",
"homepage": "http://github.com/JayBizzle/Laravel-Crawler-Detect",
"keywords": [
"bot",
"crawler",
"crawler detect",
"crawler detector",
"crawlerdetect",
"detect",
"laravel",
"php crawler detect",
"spider",
"user-agent"
],
"time": "2017-06-01T20:29:30+00:00"
},
{
"name": "kyslik/column-sortable",
"version": "6.3.0",

View File

@@ -231,6 +231,7 @@ return [
'View' => Illuminate\Support\Facades\View::class,
'Image' => Intervention\Image\Facades\Image::class,
'Stripe' => Cartalyst\Stripe\Laravel\Facades\Stripe::class,
'Crawler' => Jaybizzle\LaravelCrawlerDetect\Facades\LaravelCrawlerDetect::class,
],
'deploy_secret' => env('APP_DEPLOY_SECRET'),

View File

@@ -2,7 +2,7 @@
return [
'version' => '1.7.7',
'version' => '1.7.10',
// Define size of chunk uploaded by MB. E.g. integer 128 means chunk size will be 128MB.
'chunk_size' => env('CHUNK_SIZE', '128'),

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddExpirationAtAttributeToSharesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('shares', function (Blueprint $table) {
$table->integer('expire_in')->after('password')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('shares', function (Blueprint $table) {
//
});
}
}

View File

@@ -8,6 +8,7 @@
AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/webm .webm
<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 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

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

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

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

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

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

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

View File

@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{584:function(e,t,r){"use strict";r.r(t);var n=r(7);function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var c={name:"SetupWizard",computed:function(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}({},Object(n.b)(["config"])),mounted:function(){"setup-done"!==this.config.installation&&"quiet-update"!==this.config.installation||this.$router.push({name:"SignIn"})}},u=r(0),a=Object(u.a)(c,(function(){var e=this.$createElement;return(this._self._c||e)("router-view")}),[],!1,null,null,null);t.default=a.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{oBQg:function(e,t,r){"use strict";r.r(t);var n=r("L2JU");function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var c={name:"SetupWizard",computed:function(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}({},Object(n.b)(["config"])),mounted:function(){"setup-done"!==this.config.installation&&"quiet-update"!==this.config.installation||this.$router.push({name:"SignIn"})}},u=r("KHd+"),a=Object(u.a)(c,(function(){var e=this.$createElement;return(this._self._c||e)("router-view")}),[],!1,null,null,null);t.default=a.exports}}]);

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

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

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

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

@@ -5,7 +5,7 @@
*/
/*!
* vue-i18n v8.21.0
* vue-i18n v8.18.2
* (c) 2020 kazuya kawaguchi
* Released under the MIT License.
*/
@@ -17,7 +17,7 @@
*/
/**
* vee-validate v3.3.9
* vee-validate v3.3.7
* (c) 2020 Abdelrahman Awad
* @license MIT
*/

View File

@@ -1,66 +1,66 @@
{
"/chunks/files~chunks/shared-files~chunks/shared-page~chunks/trash.js": "/chunks/files~chunks/shared-files~chunks/shared-page~chunks/trash.js",
"/js/main.js": "/js/main.js",
"/css/app.css": "/css/app.css",
"/chunks/admin.js": "/chunks/admin.js",
"/chunks/admin-account.js": "/chunks/admin-account.js",
"/chunks/app-appearance.js": "/chunks/app-appearance.js",
"/chunks/app-billings.js": "/chunks/app-billings.js",
"/chunks/app-email.js": "/chunks/app-email.js",
"/chunks/app-index.js": "/chunks/app-index.js",
"/chunks/app-others.js": "/chunks/app-others.js",
"/chunks/app-payments.js": "/chunks/app-payments.js",
"/chunks/app-settings.js": "/chunks/app-settings.js",
"/chunks/app-setup.js": "/chunks/app-setup.js",
"/chunks/billings-detail.js": "/chunks/billings-detail.js",
"/chunks/contact-us.js": "/chunks/contact-us.js",
"/chunks/create-new-password.js": "/chunks/create-new-password.js",
"/chunks/dashboard.js": "/chunks/dashboard.js",
"/chunks/database.js": "/chunks/database.js",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js",
"/chunks/environment-setup.js": "/chunks/environment-setup.js",
"/chunks/files.js": "/chunks/files.js",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js",
"/chunks/installation-disclaimer.js": "/chunks/installation-disclaimer.js",
"/chunks/invoices.js": "/chunks/invoices.js",
"/chunks/landing-page.js": "/chunks/landing-page.js",
"/chunks/not-found-shared.js": "/chunks/not-found-shared.js",
"/chunks/page-edit.js": "/chunks/page-edit.js",
"/chunks/pages.js": "/chunks/pages.js",
"/chunks/plan.js": "/chunks/plan.js",
"/chunks/plan-create.js": "/chunks/plan-create.js",
"/chunks/plan-delete.js": "/chunks/plan-delete.js",
"/chunks/plan-settings.js": "/chunks/plan-settings.js",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js",
"/chunks/plans.js": "/chunks/plans.js",
"/chunks/profile.js": "/chunks/profile.js",
"/chunks/purchase-code.js": "/chunks/purchase-code.js",
"/chunks/settings.js": "/chunks/settings.js",
"/chunks/settings-create-payment-methods.js": "/chunks/settings-create-payment-methods.js",
"/chunks/settings-invoices.js": "/chunks/settings-invoices.js",
"/chunks/settings-password.js": "/chunks/settings-password.js",
"/chunks/settings-payment-methods.js": "/chunks/settings-payment-methods.js",
"/chunks/settings-storage.js": "/chunks/settings-storage.js",
"/chunks/settings-subscription.js": "/chunks/settings-subscription.js",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js",
"/chunks/shared-files.js": "/chunks/shared-files.js",
"/chunks/shared-page.js": "/chunks/shared-page.js",
"/chunks/sign-in.js": "/chunks/sign-in.js",
"/chunks/sign-up.js": "/chunks/sign-up.js",
"/chunks/stripe-credentials.js": "/chunks/stripe-credentials.js",
"/chunks/subscription-plans.js": "/chunks/subscription-plans.js",
"/chunks/subscription-service.js": "/chunks/subscription-service.js",
"/chunks/trash.js": "/chunks/trash.js",
"/chunks/upgrade.js": "/chunks/upgrade.js",
"/chunks/upgrade-billing.js": "/chunks/upgrade-billing.js",
"/chunks/upgrade-plan.js": "/chunks/upgrade-plan.js",
"/chunks/user.js": "/chunks/user.js",
"/chunks/user-create.js": "/chunks/user-create.js",
"/chunks/user-delete.js": "/chunks/user-delete.js",
"/chunks/user-detail.js": "/chunks/user-detail.js",
"/chunks/user-invoices.js": "/chunks/user-invoices.js",
"/chunks/user-password.js": "/chunks/user-password.js",
"/chunks/user-storage.js": "/chunks/user-storage.js",
"/chunks/user-subscription.js": "/chunks/user-subscription.js",
"/chunks/users.js": "/chunks/users.js"
"/chunks/files~chunks/shared-files~chunks/shared-page~chunks/trash.js": "/chunks/files~chunks/shared-files~chunks/shared-page~chunks/trash.js?id=adad12e7b42316bdd659",
"/js/main.js": "/js/main.js?id=5399021dab4b9f990f4d",
"/css/app.css": "/css/app.css?id=dbf49843b327d3936c06",
"/chunks/admin.js": "/chunks/admin.js?id=5bd95ece632ca142f035",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=b181a9ba45f475b9e004",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=f77c9be4514e7ab0ad0e",
"/chunks/app-billings.js": "/chunks/app-billings.js?id=24259b32506484062990",
"/chunks/app-email.js": "/chunks/app-email.js?id=471301be8d4dbb371fa0",
"/chunks/app-index.js": "/chunks/app-index.js?id=ded9a59aa4d4d8040637",
"/chunks/app-others.js": "/chunks/app-others.js?id=d1158ce36ac84d7fb317",
"/chunks/app-payments.js": "/chunks/app-payments.js?id=c4a896c3218713699b17",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=8499d3cb5a2c547d3d69",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=f8769c14859175aad49b",
"/chunks/billings-detail.js": "/chunks/billings-detail.js?id=410da17c566b388cb0a5",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=153e8ac7ba24a14f2e1a",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=9e9d35c199787d991445",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=4f379c21c8f1df14cda7",
"/chunks/database.js": "/chunks/database.js?id=99736b26537c8bb61a33",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=2e3af103d13536c50757",
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=48fa8bb643132a82bdaa",
"/chunks/files.js": "/chunks/files.js?id=0a08eb40be8f2c511ded",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=a84f7a6d4e4e05af0701",
"/chunks/installation-disclaimer.js": "/chunks/installation-disclaimer.js?id=54cf8dbd4d75fd0b2add",
"/chunks/invoices.js": "/chunks/invoices.js?id=c20b841c75005fdacde6",
"/chunks/landing-page.js": "/chunks/landing-page.js?id=b69d1af44673ddfb69d3",
"/chunks/not-found-shared.js": "/chunks/not-found-shared.js?id=286d18bed681c67e5330",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=2ff6bfeb6d9c43014d69",
"/chunks/pages.js": "/chunks/pages.js?id=49a51fc783d155aa8132",
"/chunks/plan.js": "/chunks/plan.js?id=bbea8c9e9f807d9cedc5",
"/chunks/plan-create.js": "/chunks/plan-create.js?id=0149731ddb88c33b066d",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=e63e243dccb487fa18f5",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=83517dd417b8641c60c8",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=26e1aabafdc06d069fa3",
"/chunks/plans.js": "/chunks/plans.js?id=0b1d2058ba59c955947b",
"/chunks/profile.js": "/chunks/profile.js?id=9e3ff146e95d8a719add",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=696427718c821f482c94",
"/chunks/settings.js": "/chunks/settings.js?id=51495831f7bbad060a00",
"/chunks/settings-create-payment-methods.js": "/chunks/settings-create-payment-methods.js?id=007277c68fce4a7ce5e9",
"/chunks/settings-invoices.js": "/chunks/settings-invoices.js?id=82cbe975767641ad178e",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=6e9b879329675433551d",
"/chunks/settings-payment-methods.js": "/chunks/settings-payment-methods.js?id=9f6fdc546cfa5f98796e",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=9716c15688051b9c9b20",
"/chunks/settings-subscription.js": "/chunks/settings-subscription.js?id=e4176c53674c2e6d440f",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=47090233afc7b0cdf855",
"/chunks/shared-files.js": "/chunks/shared-files.js?id=bc0b14705784b1ff6c82",
"/chunks/shared-page.js": "/chunks/shared-page.js?id=6c9bf5f496f4b8917fef",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=0c9fe096135be58283b6",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=eaa8bc2819a9cc19dbc7",
"/chunks/stripe-credentials.js": "/chunks/stripe-credentials.js?id=d384dddfe76d89164df3",
"/chunks/subscription-plans.js": "/chunks/subscription-plans.js?id=d4434431a9c8fa3ffc2b",
"/chunks/subscription-service.js": "/chunks/subscription-service.js?id=175f558c3e09887846a5",
"/chunks/trash.js": "/chunks/trash.js?id=e00ce8bde9ea638f5049",
"/chunks/upgrade.js": "/chunks/upgrade.js?id=03eccfa25c668325efd0",
"/chunks/upgrade-billing.js": "/chunks/upgrade-billing.js?id=4921e1ce22bfdab9f014",
"/chunks/upgrade-plan.js": "/chunks/upgrade-plan.js?id=7b02fafcca0029762a66",
"/chunks/user.js": "/chunks/user.js?id=d842e0d6859c94caa23d",
"/chunks/user-create.js": "/chunks/user-create.js?id=4735bda3b876200f0511",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=cea21a2d091f1f02e179",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=b3f5d20c34a5b0bf9ff6",
"/chunks/user-invoices.js": "/chunks/user-invoices.js?id=b73fa5a127374d1de1de",
"/chunks/user-password.js": "/chunks/user-password.js?id=466b113e32397b2f2f33",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=7e19cc06447c776ce504",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=45c971c8c4912d44bc42",
"/chunks/users.js": "/chunks/users.js?id=362b167df913626d3d92"
}

6
public/phpinfo.php Normal file
View File

@@ -0,0 +1,6 @@
<?php
// Show all information, defaults to INFO_ALL
phpinfo();
?>

View File

@@ -6,6 +6,9 @@
<div id="application-wrapper" v-if="! isGuestLayout">
<!-- Full File Preview -->
<FileFullPreview />
<!--Mobile Navigation-->
<MobileNavigation />
@@ -45,6 +48,7 @@
<script>
import ToastrWrapper from '@/components/Others/Notifications/ToastrWrapper'
import FileFullPreview from '@/components/FilesView/FileFullPreview'
import MobileNavigation from '@/components/Others/MobileNavigation'
import CookieDisclaimer from '@/components/Others/CookieDisclaimer'
import MobileMenu from '@/components/FilesView/MobileMenu'
@@ -64,6 +68,7 @@
components: {
MobileNavigation,
CookieDisclaimer,
FileFullPreview,
ToastrWrapper,
ShareCreate,
MobileMenu,
@@ -80,27 +85,27 @@
]),
isGuestLayout() {
return (includes([
'InstallationDisclaimer',
'SubscriptionService',
'StripeCredentials',
'SubscriptionPlans',
'ForgottenPassword',
'CreateNewPassword',
'EnvironmentSetup',
'VerifyByPassword',
'SaaSLandingPage',
'BillingsDetail',
'NotFoundShared',
'AdminAccount',
'PurchaseCode',
'DynamicPage',
'SharedPage',
'ContactUs',
'AppSetup',
'Database',
'Upgrade',
'SignIn',
'SignUp',
'InstallationDisclaimer',
'SubscriptionService',
'StripeCredentials',
'SubscriptionPlans',
'ForgottenPassword',
'CreateNewPassword',
'EnvironmentSetup',
'VerifyByPassword',
'SaaSLandingPage',
'BillingsDetail',
'NotFoundShared',
'AdminAccount',
'PurchaseCode',
'DynamicPage',
'SharedPage',
'ContactUs',
'AppSetup',
'Database',
'Upgrade',
'SignIn',
'SignUp',
], this.$route.name)
)
}
@@ -147,7 +152,7 @@
</script>
<style lang="scss">
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600;700;800;900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@200;300;400;600;700;800;900&display=swap');
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';

File diff suppressed because it is too large Load Diff

View File

@@ -1,366 +1,411 @@
<template>
<div id="desktop-toolbar">
<div class="toolbar-wrapper">
<div id="desktop-toolbar">
<div class="toolbar-wrapper">
<!-- Go back-->
<div class="toolbar-go-back" v-if="homeDirectory">
<div @click="goBack" class="go-back-button">
<chevron-left-icon
size="17"
:class="{ 'is-active': browseHistory.length > 1 }"
class="icon-back"
></chevron-left-icon>
<!-- Go back-->
<div class="toolbar-go-back" v-if="homeDirectory">
<div @click="goBack" class="go-back-button">
<chevron-left-icon size="17" :class="{'is-active': browseHistory.length > 1}" class="icon-back"></chevron-left-icon>
<span class="back-directory-title">
{{ directoryName }}
</span>
<span class="back-directory-title">
{{ directoryName }}
</span>
<span @click.stop="folderActions" v-if="browseHistory.length > 1 && $isThisLocation(['base', 'public'])" class="folder-options" id="folder-actions">
<more-horizontal-icon size="14" class="icon-more"></more-horizontal-icon>
</span>
</div>
</div>
<!-- Tools-->
<div class="toolbar-tools">
<!--Search bar-->
<div class="toolbar-button-wrapper">
<SearchBar/>
</div>
<!--Files controlls-->
<div class="toolbar-button-wrapper" v-if="$checkPermission(['master', 'editor'])">
<ToolbarButtonUpload
:class="{'is-inactive': canUploadInView || ! hasCapacity}"
:action="$t('actions.upload')"
/>
<ToolbarButton
:class="{'is-inactive': canCreateFolderInView}"
@click.native="createFolder"
source="folder-plus"
:action="$t('actions.create_folder')"
/>
</div>
<div class="toolbar-button-wrapper" v-if="$checkPermission(['master', 'editor'])">
<ToolbarButton
source="move"
:class="{'is-inactive': canMoveInView}"
:action="$t('actions.move')"
@click.native="moveItem"
/>
<ToolbarButton
v-if="! $isThisLocation(['public'])"
source="share"
:class="{'is-inactive': canShareInView}"
:action="$t('actions.share')"
@click.native="shareItem"
/>
<ToolbarButton
source="trash"
:class="{'is-inactive': canDeleteInView}"
:action="$t('actions.delete')"
@click.native="deleteItem"
/>
</div>
<!--View options-->
<div class="toolbar-button-wrapper">
<ToolbarButton
:source="preview"
:action="$t('actions.preview')"
@click.native="$store.dispatch('changePreviewType')"
/>
<ToolbarButton
:class="{ active: fileInfoVisible }"
@click.native="$store.dispatch('fileInfoToggle')"
source="info"
/>
</div>
</div>
<span
@click.stop="folderActions"
v-if="
browseHistory.length > 1 && $isThisLocation(['base', 'public'])
"
class="folder-options"
id="folder-actions"
>
<more-horizontal-icon
size="14"
class="icon-more"
></more-horizontal-icon>
</span>
</div>
<UploadProgress />
</div>
<!-- Tools-->
<div class="toolbar-tools">
<!--Search bar-->
<div class="toolbar-button-wrapper">
<SearchBar />
</div>
<!--Files controlls-->
<div
class="toolbar-button-wrapper"
v-if="$checkPermission(['master', 'editor'])"
>
<ToolbarButtonUpload
:class="{ 'is-inactive': canUploadInView || !hasCapacity }"
:action="$t('actions.upload')"
/>
<ToolbarButton
:class="{ 'is-inactive': canCreateFolderInView }"
@click.native="createFolder"
source="folder-plus"
:action="$t('actions.create_folder')"
/>
</div>
<div
class="toolbar-button-wrapper"
v-if="$checkPermission(['master', 'editor'])"
>
<ToolbarButton
source="move"
:class="{ 'is-inactive': canMoveInView }"
:action="$t('actions.move')"
@click.native="moveItem"
/>
<ToolbarButton
v-if="!$isThisLocation(['public'])"
source="share"
:class="{ 'is-inactive': canShareInView }"
:action="$t('actions.share')"
@click.native="shareItem"
/>
<ToolbarButton
source="trash"
:class="{ 'is-inactive': canDeleteInView }"
:action="$t('actions.delete')"
@click.native="deleteItem"
/>
</div>
<!--View options-->
<div class="toolbar-button-wrapper">
<ToolbarButton
:source="preview"
:action="$t('actions.preview')"
@click.native="$store.dispatch('changePreviewType')"
/>
<ToolbarButton
:class="{ active: fileInfoVisible }"
@click.native="$store.dispatch('fileInfoToggle')"
source="info"
/>
</div>
</div>
</div>
<UploadProgress />
</div>
</template>
<script>
import ToolbarButtonUpload from '@/components/FilesView/ToolbarButtonUpload'
import { ChevronLeftIcon, MoreHorizontalIcon } from 'vue-feather-icons'
import UploadProgress from '@/components/FilesView/UploadProgress'
import ToolbarButton from '@/components/FilesView/ToolbarButton'
import SearchBar from '@/components/FilesView/SearchBar'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
import {last} from 'lodash'
import ToolbarButtonUpload from "@/components/FilesView/ToolbarButtonUpload";
import { ChevronLeftIcon, MoreHorizontalIcon } from "vue-feather-icons";
import UploadProgress from "@/components/FilesView/UploadProgress";
import ToolbarButton from "@/components/FilesView/ToolbarButton";
import SearchBar from "@/components/FilesView/SearchBar";
import { mapGetters } from "vuex";
import { events } from "@/bus";
import { last } from "lodash";
export default {
name: 'ToolBar',
components: {
ToolbarButtonUpload,
MoreHorizontalIcon,
ChevronLeftIcon,
UploadProgress,
ToolbarButton,
SearchBar
},
computed: {
...mapGetters([
'FilePreviewType',
'fileInfoVisible',
'fileInfoDetail',
'currentFolder',
'browseHistory',
'homeDirectory',
]),
hasCapacity() {
export default {
name: "ToolBar",
components: {
ToolbarButtonUpload,
MoreHorizontalIcon,
ChevronLeftIcon,
UploadProgress,
ToolbarButton,
SearchBar,
},
computed: {
...mapGetters([
"FilePreviewType",
"fileInfoVisible",
"fileInfoDetail",
"currentFolder",
"browseHistory",
"homeDirectory",
]),
hasCapacity() {
// Check if set storage limitation
if (!this.$store.getters.config.storageLimit) return true;
// Check if set storage limitation
if (! this.$store.getters.config.storageLimit)
return true
// Check if is loaded user
if (!this.$store.getters.user) return true;
// Check if is loaded user
if (! this.$store.getters.user )
return true
// Check if user has storage
return (
this.$store.getters.user.relationships.storage.data.attributes.used <=
100
);
},
directoryName() {
return this.currentFolder
? this.currentFolder.name
: this.homeDirectory.name;
},
preview() {
return this.FilePreviewType === "list" ? "th" : "th-list";
},
canCreateFolderInView() {
return !this.$isThisLocation(["base", "public"]);
},
canDeleteInView() {
return !this.$isThisLocation([
"trash",
"trash-root",
"base",
"participant_uploads",
"latest",
"shared",
"public",
]);
},
canUploadInView() {
return !this.$isThisLocation(["base", "public"]);
},
canMoveInView() {
return !this.$isThisLocation([
"base",
"participant_uploads",
"latest",
"shared",
"public",
]);
},
canShareInView() {
return !this.$isThisLocation([
"base",
"participant_uploads",
"latest",
"shared",
"public",
]);
},
},
methods: {
goBack() {
// Get previous folder
let previousFolder = last(this.browseHistory);
// Check if user has storage
return this.$store.getters.user.relationships.storage.data.attributes.used <= 100
},
directoryName() {
return this.currentFolder ? this.currentFolder.name : this.homeDirectory.name
},
preview() {
return this.FilePreviewType === 'list' ? 'th' : 'th-list'
},
canCreateFolderInView() {
return ! this.$isThisLocation(['base', 'public'])
},
canDeleteInView() {
return ! this.$isThisLocation(['trash', 'trash-root', 'base', 'participant_uploads', 'latest', 'shared', 'public'])
},
canUploadInView() {
return ! this.$isThisLocation(['base', 'public'])
},
canMoveInView() {
return ! this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared', 'public'])
},
canShareInView() {
return ! this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared', 'public'])
}
},
methods: {
goBack() {
// Get previous folder
let previousFolder = last(this.browseHistory)
if (!previousFolder) return;
if (! previousFolder)
return
if (previousFolder.location === 'trash-root') {
this.$store.dispatch('getTrash')
} else if (previousFolder.location === 'shared') {
this.$store.dispatch('getShared')
} else {
if ( this.$isThisLocation('public') ) {
this.$store.dispatch('browseShared', [{folder: previousFolder, back: true, init: false}])
} else {
this.$store.dispatch('getFolder', [{folder: previousFolder, back: true, init: false}])
}
}
},
folderActions() {
events.$emit('folder:actions', this.currentFolder)
},
deleteItem() {
events.$emit('items:delete')
},
createFolder() {
this.$createFolder()
},
moveItem() {
events.$emit('popup:open', {name: 'move', item: this.fileInfoDetail})
},
shareItem() {
if (this.fileInfoDetail.shared) {
events.$emit('popup:open', {name: 'share-edit', item: this.fileInfoDetail})
} else {
events.$emit('popup:open', {name: 'share-create', item: this.fileInfoDetail})
}
}
},
}
if (previousFolder.location === "trash-root") {
this.$store.dispatch("getTrash");
} else if (previousFolder.location === "shared") {
this.$store.dispatch("getShared");
} else {
if (this.$isThisLocation("public")) {
this.$store.dispatch("browseShared", [
{ folder: previousFolder, back: true, init: false },
]);
} else {
this.$store.dispatch("getFolder", [
{ folder: previousFolder, back: true, init: false },
]);
}
}
},
folderActions() {
events.$emit("folder:actions", this.currentFolder);
},
deleteItem() {
events.$emit("items:delete");
},
createFolder() {
this.$createFolder();
},
moveItem() {
events.$emit("popup:open", { name: "move", item: this.fileInfoDetail });
},
shareItem() {
if (this.fileInfoDetail) {
//ADD BY M
if (this.fileInfoDetail.shared) {
events.$emit("popup:open", {
name: "share-edit",
item: this.fileInfoDetail,
});
} else {
events.$emit("popup:open", {
name: "share-create",
item: this.fileInfoDetail,
});
}
}
},
},
};
</script>
<style scoped lang="scss">
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
@import "@assets/vue-file-manager/_variables";
@import "@assets/vue-file-manager/_mixins";
.toolbar-wrapper {
padding-top: 10px;
padding-bottom: 10px;
display: flex;
position: relative;
z-index: 2;
.toolbar-wrapper {
padding-top: 10px;
padding-bottom: 10px;
display: flex;
position: relative;
z-index: 2;
> div {
flex-grow: 1;
align-self: center;
white-space: nowrap;
}
> div {
flex-grow: 1;
align-self: center;
white-space: nowrap;
}
}
.directory-name {
vertical-align: middle;
@include font-size(17);
color: $text;
font-weight: 700;
max-width: 220px;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
.icon-back {
vertical-align: middle;
cursor: pointer;
margin-right: 6px;
opacity: 0.15;
pointer-events: none;
@include transition(150ms);
&.is-active {
opacity: 1;
pointer-events: initial;
}
}
.toolbar-go-back {
cursor: pointer;
.folder-options {
vertical-align: middle;
margin-left: 6px;
padding: 1px 4px;
line-height: 0;
border-radius: 3px;
@include transition(150ms);
svg circle {
@include transition(150ms);
}
.directory-name {
vertical-align: middle;
@include font-size(17);
color: $text;
font-weight: 700;
max-width: 220px;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
&:hover {
background: $light_background;
svg circle {
stroke: $theme;
}
}
.icon-back {
vertical-align: middle;
cursor: pointer;
margin-right: 6px;
opacity: 0.15;
pointer-events: none;
@include transition(150ms);
.icon-more {
vertical-align: middle;
}
}
&.is-active {
opacity: 1;
pointer-events: initial;
.back-directory-title {
@include font-size(15);
line-height: 1;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
color: $text;
}
}
.toolbar-position {
text-align: center;
span {
@include font-size(17);
font-weight: 600;
}
}
.toolbar-tools {
text-align: right;
.toolbar-button-wrapper {
margin-left: 28px;
display: inline-block;
vertical-align: middle;
&:first-child {
margin-left: 0 !important;
}
}
.button {
margin-left: 5px;
&.active {
/deep/ svg {
line,
circle {
stroke: $theme;
}
}
}
.toolbar-go-back {
cursor: pointer;
.folder-options {
vertical-align: middle;
margin-left: 6px;
padding: 1px 4px;
line-height: 0;
border-radius: 3px;
@include transition(150ms);
svg circle {
@include transition(150ms);
}
&:hover {
background: $light_background;
svg circle {
stroke: $theme;
}
}
.icon-more {
vertical-align: middle;
}
}
.back-directory-title {
@include font-size(15);
line-height: 1;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
color: $text;
}
&.is-inactive {
opacity: 0.25;
pointer-events: none;
}
.toolbar-position {
text-align: center;
&:first-child {
margin-left: 0;
}
}
}
span {
@include font-size(17);
font-weight: 600;
}
@media only screen and (max-width: 1024px) {
.toolbar-go-back .back-directory-title {
max-width: 120px;
}
.toolbar-tools {
.button {
margin-left: 0;
height: 40px;
width: 40px;
}
.toolbar-tools {
text-align: right;
.toolbar-button-wrapper {
margin-left: 25px;
}
}
}
.toolbar-button-wrapper {
margin-left: 28px;
display: inline-block;
vertical-align: middle;
@media only screen and (max-width: 960px) {
#desktop-toolbar {
display: none;
}
}
&:first-child {
margin-left: 0 !important;
}
}
@media (prefers-color-scheme: dark) {
.toolbar .directory-name {
color: $dark_mode_text_primary;
}
.button {
margin-left: 5px;
&.active {
/deep/ svg {
line, circle {
stroke: $theme;
}
}
}
&.is-inactive {
opacity: 0.25;
pointer-events: none;
}
&:first-child {
margin-left: 0;
}
}
.toolbar-go-back {
.back-directory-title {
color: $dark_mode_text_primary;
}
@media only screen and (max-width: 1024px) {
.toolbar-go-back .back-directory-title {
max-width: 120px;
}
.toolbar-tools {
.button {
margin-left: 0;
height: 40px;
width: 40px;
}
.toolbar-button-wrapper {
margin-left: 25px;
}
}
}
@media only screen and (max-width: 960px) {
#desktop-toolbar {
display: none;
}
}
@media (prefers-color-scheme: dark) {
.toolbar .directory-name {
color: $dark_mode_text_primary;
}
.toolbar-go-back {
.back-directory-title {
color: $dark_mode_text_primary;
}
.folder-options {
&:hover {
background: $dark_mode_foreground;
}
}
}
.folder-options {
&:hover {
background: $dark_mode_foreground;
}
}
}
}
</style>

View File

@@ -0,0 +1,96 @@
<template>
<div
v-if="showFullPreview"
class="file-full-preview-wrapper"
id="fileFullPreview"
ref="filePreview"
tabindex="-1"
@click="closeContextMenu"
@keydown.esc=";(showFullPreview = false), hideContextMenu()"
@keydown.right="next"
@keydown.left="prev"
>
<FilePreviewNavigationPanel />
<MediaFullPreview />
<FilePreviewActions />
</div>
</template>
<script>
import { events } from '@/bus'
import { mapGetters } from 'vuex'
import MediaFullPreview from '@/components/FilesView/MediaFullPreview'
import FilePreviewActions from '@/components/FilesView/FilePreviewActions'
import FilePreviewNavigationPanel from '@/components/FilesView/FilePreviewNavigationPanel'
export default {
name: 'FileFullPreview',
components: {
MediaFullPreview,
FilePreviewNavigationPanel,
FilePreviewActions
},
computed: {
...mapGetters(['fileInfoDetail', 'data'])
},
data() {
return {
showFullPreview: false
}
},
methods: {
closeContextMenu(event) {
if ((event.target.parentElement.id || event.target.id) === 'fast-preview-menu') {
return
} else {
events.$emit('showContextMenuPreview:hide')
}
},
next: function() {
events.$emit('filePreviewAction:next')
},
prev: function() {
events.$emit('filePreviewAction:prev')
},
hideContextMenu() {
events.$emit('showContextMenuPreview:hide')
}
},
updated() {
//Focus file preview for key binding
if (this.showFullPreview) {
this.$refs.filePreview.focus()
}
},
mounted() {
events.$on('fileFullPreview:show', () => {
this.showFullPreview = true
})
events.$on('fileFullPreview:hide', () => {
this.showFullPreview = false
events.$emit('hide:mobile-navigation')
})
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
.file-full-preview-wrapper {
width: 100%;
height: 100%;
position: absolute;
z-index: 7;
background-color: white;
}
@media (prefers-color-scheme: dark) {
.file-full-preview-wrapper {
background-color: $dark_mode_background;
}
}
</style>

View File

@@ -101,9 +101,19 @@
isFile() {
return this.data.type !== 'folder' && this.data.type !== 'image'
},
isPdf() {
return this.data.mimetype === 'pdf'
},
isImage() {
return this.data.type === 'image'
},
isVideo() {
return this.data.type === 'video'
},
isAudio() {
let mimetypes = ['mpeg', 'mp3', 'mp4', 'wan', 'flac']
return mimetypes.includes(this.data.mimetype) && this.data.type === 'audio'
},
canEditName() {
return !this.$isMobile()
&& !this.$isThisLocation(['trash', 'trash-root'])
@@ -166,6 +176,12 @@
}
}
if (this.$isMobile()) {
if (this.isImage || this.isVideo || this.isAudio) {
events.$emit('fileFullPreview:show')
}
}
// Load file info detail
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
@@ -180,11 +196,11 @@
return
},
goToItem() {
if (this.isImage) {
this.$openImageOnNewTab(this.data.file_url)
if (this.isImage || this.isVideo || this.isAudio) {
events.$emit('fileFullPreview:show')
}
if (this.isFile) {
if (this.isFile && !this.isPdf && !this.isVideo && !this.isAudio) {
this.$downloadFile(
this.data.file_url,
this.data.name + '.' + this.data.mimetype

View File

@@ -1,473 +1,456 @@
<template>
<div
class="file-wrapper"
@click.stop="clickedItem"
@dblclick="goToItem"
spellcheck="false"
>
<!--List preview-->
<div
:draggable="canDrag"
@dragstart="$emit('dragstart')"
@drop="
<div class="file-wrapper" @click.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
<!--List preview-->
<div
:draggable="canDrag"
@dragstart="$emit('dragstart')"
@drop="
$emit('drop')
area = false
"
@dragleave="dragLeave"
@dragover.prevent="dragEnter"
class="file-item"
:class="{ 'is-clicked': isClicked, 'is-dragenter': area }"
>
<!--Thumbnail for item-->
<div class="icon-item">
<!--If is file or image, then link item-->
<span v-if="isFile" class="file-icon-text">
{{ data.mimetype | limitCharacters }}
</span>
@dragleave="dragLeave"
@dragover.prevent="dragEnter"
class="file-item"
:class="{ 'is-clicked': isClicked, 'is-dragenter': area }"
>
<!--Thumbnail for item-->
<div class="icon-item">
<!--If is file or image, then link item-->
<span v-if="isFile" class="file-icon-text">
{{ data.mimetype | limitCharacters }}
</span>
<!--Folder thumbnail-->
<FontAwesomeIcon v-if="isFile" class="file-icon" icon="file"/>
<!--Folder thumbnail-->
<FontAwesomeIcon v-if="isFile" class="file-icon" icon="file" />
<!--Image thumbnail-->
<img v-if="isImage" class="image" :src="data.thumbnail" :alt="data.name"/>
<!--Image thumbnail-->
<img v-if="isImage" class="image" :src="data.thumbnail" :alt="data.name" />
<!--Else show only folder icon-->
<FontAwesomeIcon v-if="isFolder" :class="{'is-deleted': isDeleted}" class="folder-icon" icon="folder"/>
</div>
<!--Else show only folder icon-->
<FontAwesomeIcon v-if="isFolder" :class="{ 'is-deleted': isDeleted }" class="folder-icon" icon="folder" />
</div>
<!--Name-->
<div class="item-name">
<!--Name-->
<b
ref="name"
@input="renameItem"
:contenteditable="canEditName"
class="name"
>
{{ itemName }}
</b>
<!--Name-->
<div class="item-name">
<!--Name-->
<b ref="name" @input="renameItem" :contenteditable="canEditName" class="name">
{{ itemName }}
</b>
<div class="item-info">
<div class="item-info">
<!--Shared Icon-->
<div v-if="$checkPermission('master') && data.shared" class="item-shared">
<link-icon size="12" class="shared-icon"></link-icon>
</div>
<!--Shared Icon-->
<div v-if="$checkPermission('master') && data.shared" class="item-shared">
<link-icon size="12" class="shared-icon"></link-icon>
</div>
<!--Participant owner Icon-->
<div v-if="$checkPermission('master') && data.user_scope !== 'master'" class="item-shared">
<user-plus-icon size="12" class="shared-icon"></user-plus-icon>
</div>
<!--Participant owner Icon-->
<div v-if="$checkPermission('master') && data.user_scope !== 'master'" class="item-shared">
<user-plus-icon size="12" class="shared-icon"></user-plus-icon>
</div>
<!--Filesize and timestamp-->
<span v-if="!isFolder" class="item-size">{{ data.filesize }}, {{ timeStamp }}</span>
<!--Filesize and timestamp-->
<span v-if="! isFolder" class="item-size">{{ data.filesize }}, {{ timeStamp }}</span>
<!--Folder item counts-->
<span v-if="isFolder" class="item-length"> {{ folderItems == 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }}, {{ timeStamp }} </span>
</div>
</div>
<!--Folder item counts-->
<span v-if="isFolder" class="item-length">
{{ folderItems == 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }}, {{ timeStamp }}
</span>
</div>
</div>
<!--Go Next icon-->
<div class="actions" v-if="$isMobile() && ! ( $checkPermission('visitor') && isFolder )">
<!--Go Next icon-->
<div class="actions" v-if="$isMobile() && !($checkPermission('visitor') && isFolder)">
<span @click.stop="showItemActions" class="show-actions">
<FontAwesomeIcon icon="ellipsis-v" class="icon-action"></FontAwesomeIcon>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { LinkIcon, UserPlusIcon } from 'vue-feather-icons'
import {debounce} from 'lodash'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
import { LinkIcon, UserPlusIcon } from 'vue-feather-icons'
import { debounce } from 'lodash'
import { mapGetters } from 'vuex'
import { events } from '@/bus'
export default {
name: 'FileItemList',
props: ['data'],
components: {
UserPlusIcon,
LinkIcon,
},
computed: {
...mapGetters(['FilePreviewType']),
isFolder() {
return this.data.type === 'folder'
},
isFile() {
return this.data.type !== 'folder' && this.data.type !== 'image'
},
isImage() {
return this.data.type === 'image'
},
canEditName() {
return !this.$isMobile()
&& !this.$isThisLocation(['trash', 'trash-root'])
&& !this.$checkPermission('visitor')
&& !(this.sharedDetail && this.sharedDetail.type === 'file')
},
canDrag() {
return !this.isDeleted && this.$checkPermission(['master', 'editor'])
},
timeStamp() {
return this.data.deleted_at ? this.$t('item_thumbnail.deleted_at', {time: this.data.deleted_at}) : this.data.created_at
},
folderItems() {
return this.data.deleted_at ? this.data.trashed_items : this.data.items
},
isDeleted() {
return this.data.deleted_at ? true : false
}
},
filters: {
limitCharacters(str) {
export default {
name: 'FileItemList',
props: ['data'],
components: {
UserPlusIcon,
LinkIcon
},
computed: {
...mapGetters(['FilePreviewType']),
isFolder() {
return this.data.type === 'folder'
},
isFile() {
return this.data.type !== 'folder' && this.data.type !== 'image'
},
isImage() {
return this.data.type === 'image'
},
isPdf() {
return this.data.mimetype === 'pdf'
},
isVideo() {
return this.data.type === 'video'
},
isAudio() {
let mimetypes = ['mpeg', 'mp3', 'mp4', 'wan', 'flac']
return mimetypes.includes(this.data.mimetype) && this.data.type === 'audio'
},
canEditName() {
return !this.$isMobile() && !this.$isThisLocation(['trash', 'trash-root']) && !this.$checkPermission('visitor') && !(this.sharedDetail && this.sharedDetail.type === 'file')
},
canDrag() {
return !this.isDeleted && this.$checkPermission(['master', 'editor'])
},
timeStamp() {
return this.data.deleted_at ? this.$t('item_thumbnail.deleted_at', { time: this.data.deleted_at }) : this.data.created_at
},
folderItems() {
return this.data.deleted_at ? this.data.trashed_items : this.data.items
},
isDeleted() {
return this.data.deleted_at ? true : false
}
},
filters: {
limitCharacters(str) {
if (str.length > 3) {
return str.substring(0, 3) + '...'
} else {
return str.substring(0, 3)
}
}
},
data() {
return {
isClicked: false,
area: false,
itemName: undefined
}
},
methods: {
showItemActions() {
// Load file info detail
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
if (str.length > 3) {
return str.substring(0, 3) + '...';
} else {
return str.substring(0, 3);
}
events.$emit('mobileMenu:show')
},
dragEnter() {
if (this.data.type !== 'folder') return
}
},
data() {
return {
isClicked: false,
area: false,
itemName: undefined,
}
},
methods: {
showItemActions() {
// Load file info detail
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
this.area = true
},
dragLeave() {
this.area = false
},
clickedItem(e) {
events.$emit('contextMenu:hide')
events.$emit('fileItem:deselect')
//this.isClicked = true
// Set clicked item
this.isClicked = true
events.$emit('mobileMenu:show')
},
dragEnter() {
if (this.data.type !== 'folder') return
// Open in mobile version on first click
if (this.$isMobile() && this.isFolder) {
// Go to folder
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{ folder: this.data, back: false, init: false }])
} else {
this.$store.dispatch('getFolder', [{ folder: this.data, back: false, init: false }])
}
}
this.area = true
},
dragLeave() {
this.area = false
},
clickedItem(e) {
events.$emit('contextMenu:hide')
events.$emit('fileItem:deselect')
if (this.$isMobile()) {
if (this.isImage || this.isVideo || this.isAudio) {
events.$emit('fileFullPreview:show')
}
}
// Set clicked item
this.isClicked = true
// Load file info detail
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
// Open in mobile version on first click
if (this.$isMobile() && this.isFolder) {
// Get target classname
let itemClass = e.target.className
// Go to folder
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{folder: this.data, back: false, init: false}])
} else {
this.$store.dispatch('getFolder', [{folder: this.data, back: false, init: false}])
}
}
if (['name', 'icon', 'file-link', 'file-icon-text'].includes(itemClass)) return
},
goToItem() {
if (this.isImage || this.isVideo || this.isAudio) {
events.$emit('fileFullPreview:show')
}
// Load file info detail
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
if (this.isFile && !this.isPdf && !this.isVideo && !this.isAudio) {
this.$downloadFile(this.data.file_url, this.data.name + '.' + this.data.mimetype)
}
// Get target classname
let itemClass = e.target.className
if (this.isFolder) {
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{ folder: this.data, back: false, init: false }])
} else {
this.$store.dispatch('getFolder', [{ folder: this.data, back: false, init: false }])
}
}
},
renameItem: debounce(function(e) {
// Prevent submit empty string
if (e.target.innerText.trim() === '') return
if (['name', 'icon', 'file-link', 'file-icon-text'].includes(itemClass))
return
},
goToItem() {
if (this.isImage) {
this.$openImageOnNewTab(this.data.file_url)
}
this.$store.dispatch('renameItem', {
unique_id: this.data.unique_id,
type: this.data.type,
name: e.target.innerText
})
}, 300)
},
created() {
this.itemName = this.data.name
if (this.isFile) {
this.$downloadFile(
this.data.file_url,
this.data.name + '.' + this.data.mimetype
)
}
events.$on('fileItem:deselect', () => {
// Deselect file
this.isClicked = false
})
if (this.isFolder) {
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{folder: this.data, back: false, init: false}])
} else {
this.$store.dispatch('getFolder', [{folder: this.data, back: false, init: false}])
}
}
},
renameItem: debounce(function (e) {
// Prevent submit empty string
if (e.target.innerText.trim() === '') return
this.$store.dispatch('renameItem', {
unique_id: this.data.unique_id,
type: this.data.type,
name: e.target.innerText
})
}, 300)
},
created() {
this.itemName = this.data.name
events.$on('fileItem:deselect', () => {
// Deselect file
this.isClicked = false
})
// Change item name
events.$on('change:name', (item) => {
if (this.data.unique_id == item.unique_id) this.itemName = item.name
})
},
}
// Change item name
events.$on('change:name', (item) => {
if (this.data.unique_id == item.unique_id) this.itemName = item.name
})
}
}
</script>
<style scoped lang="scss">
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
.file-wrapper {
user-select: none;
position: relative;
.file-wrapper {
user-select: none;
position: relative;
&:hover {
border-color: transparent;
}
&:hover {
border-color: transparent;
}
.actions {
text-align: right;
width: 50px;
.actions {
text-align: right;
width: 50px;
.show-actions {
cursor: pointer;
padding: 12px 6px 12px;
.show-actions {
cursor: pointer;
padding: 12px 6px 12px;
.icon-action {
@include font-size(14);
.icon-action {
@include font-size(14);
path {
fill: $theme;
}
}
}
}
path {
fill: $theme;
}
}
}
}
.item-name {
display: block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.item-name {
display: block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.item-info {
display: block;
line-height: 1;
}
.item-info {
display: block;
line-height: 1;
}
.item-shared {
display: inline-block;
.item-shared {
display: inline-block;
.label {
@include font-size(12);
font-weight: 400;
color: $theme;
}
.label {
@include font-size(12);
font-weight: 400;
color: $theme;
}
.shared-icon {
vertical-align: middle;
.shared-icon {
vertical-align: middle;
path, circle, line {
stroke: $theme;
}
}
}
path,
circle,
line {
stroke: $theme;
}
}
}
.item-size,
.item-length {
@include font-size(11);
font-weight: 400;
color: rgba($text, 0.7);
}
.item-size,
.item-length {
@include font-size(11);
font-weight: 400;
color: rgba($text, 0.7);
}
.name {
white-space: nowrap;
.name {
white-space: nowrap;
&[contenteditable] {
-webkit-user-select: text;
user-select: text;
}
&[contenteditable] {
-webkit-user-select: text;
user-select: text;
}
&[contenteditable='true']:hover {
text-decoration: underline;
}
}
&[contenteditable='true']:hover {
text-decoration: underline;
}
}
.name {
color: $text;
@include font-size(14);
font-weight: 700;
max-height: 40px;
overflow: hidden;
text-overflow: ellipsis;
.name {
color: $text;
@include font-size(14);
font-weight: 700;
max-height: 40px;
overflow: hidden;
text-overflow: ellipsis;
&.actived {
max-height: initial;
}
}
}
&.actived {
max-height: initial;
}
}
}
&.selected {
.file-item {
background: $light_background;
}
}
&.selected {
.file-item {
background: $light_background;
}
}
.icon-item {
text-align: center;
position: relative;
flex: 0 0 50px;
line-height: 0;
margin-right: 20px;
.icon-item {
text-align: center;
position: relative;
flex: 0 0 50px;
line-height: 0;
margin-right: 20px;
.folder-icon {
@include font-size(52);
.folder-icon {
@include font-size(52);
path {
fill: $theme;
}
path {
fill: $theme;
}
&.is-deleted {
path {
fill: $dark_background;
}
}
}
&.is-deleted {
path {
fill: $dark_background;
}
}
}
.file-icon {
@include font-size(45);
.file-icon {
@include font-size(45);
path {
fill: #fafafc;
stroke: #dfe0e8;
stroke-width: 1;
}
}
path {
fill: #fafafc;
stroke: #dfe0e8;
stroke-width: 1;
}
}
.file-icon-text {
line-height: 1;
top: 40%;
@include font-size(11);
margin: 0 auto;
position: absolute;
text-align: center;
left: 0;
right: 0;
color: $theme;
font-weight: 600;
user-select: none;
max-width: 50px;
max-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.file-icon-text {
line-height: 1;
top: 40%;
@include font-size(11);
margin: 0 auto;
position: absolute;
text-align: center;
left: 0;
right: 0;
color: $theme;
font-weight: 600;
user-select: none;
max-width: 50px;
max-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.image {
object-fit: cover;
user-select: none;
max-width: 100%;
border-radius: 5px;
width: 50px;
height: 50px;
pointer-events: none;
}
}
.image {
object-fit: cover;
user-select: none;
max-width: 100%;
border-radius: 5px;
width: 50px;
height: 50px;
pointer-events: none;
}
}
.file-item {
border: 2px dashed transparent;
width: 100%;
display: flex;
align-items: center;
padding: 7px;
.file-item {
border: 2px dashed transparent;
width: 100%;
display: flex;
align-items: center;
padding: 7px;
&.is-dragenter {
border: 2px dashed $theme;
border-radius: 8px;
}
&.is-dragenter {
border: 2px dashed $theme;
border-radius: 8px;
}
&:hover,
&.is-clicked {
border-radius: 8px;
background: $light_background;
&:hover,
&.is-clicked {
border-radius: 8px;
background: $light_background;
.item-name .name {
color: $theme;
}
}
}
}
.item-name .name {
color: $theme;
}
}
}
}
@media (prefers-color-scheme: dark) {
@media (prefers-color-scheme: dark) {
.file-wrapper {
.icon-item {
.file-icon {
path {
fill: $dark_mode_foreground;
stroke: #2f3c54;
}
}
.file-wrapper {
.folder-icon {
&.is-deleted {
path {
fill: lighten($dark_mode_foreground, 5%);
}
}
}
}
.icon-item {
.file-icon {
.file-item {
&:hover,
&.is-clicked {
background: $dark_mode_foreground;
path {
fill: $dark_mode_foreground;
stroke: #2F3C54;
}
}
.file-icon {
path {
fill: $dark_mode_background;
}
}
}
}
.folder-icon {
.item-name {
.name {
color: $dark_mode_text_primary;
}
&.is-deleted {
path {
fill: lighten($dark_mode_foreground, 5%);
}
}
}
}
.file-item {
&:hover,
&.is-clicked {
background: $dark_mode_foreground;
.file-icon {
path {
fill: $dark_mode_background;
}
}
}
}
.item-name {
.name {
color: $dark_mode_text_primary;
}
.item-size,
.item-length {
color: $dark_mode_text_secondary;
}
}
}
}
</style>
.item-size,
.item-length {
color: $dark_mode_text_secondary;
}
}
}
}
</style>

View File

@@ -0,0 +1,78 @@
<template>
<div v-if="filteredFiles.length > 1">
<div @click.prevent="prev" class="prev">
<chevron-left-icon size="17"></chevron-left-icon>
</div>
<div @click.prevent="next" class="next">
<chevron-right-icon size="17"></chevron-right-icon>
</div>
</div>
</template>
<script>
import { events } from '@/bus'
import { mapGetters } from 'vuex'
import { ChevronLeftIcon, ChevronRightIcon } from 'vue-feather-icons'
export default {
name: 'FilePreviewActions',
components: {
ChevronLeftIcon,
ChevronRightIcon
},
computed: {
...mapGetters(['fileInfoDetail', 'data']),
filteredFiles() {
let filteredData = []
this.data.filter((element) => {
if (element.type == this.fileInfoDetail.type) {
filteredData.push(element)
}
})
return filteredData
}
},
methods: {
next: function() {
events.$emit('filePreviewAction:next')
},
prev: function() {
events.$emit('filePreviewAction:prev')
}
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
.prev,
.next {
cursor: pointer;
position: absolute;
top: 53.5%;
display: flex;
justify-content: center;
color: $text;
border-radius: 50%;
text-decoration: none;
user-select: none;
filter: drop-shadow(0px 1px 0 rgba(255, 255, 255, 1));
padding: 10px;
}
.next {
right: 0;
}
.prev {
left: 0;
}
@media (prefers-color-scheme: dark) {
.prev,
.next {
color: $light-text;
filter: drop-shadow(0px 1px 0 rgba(17, 19, 20, 1));
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More