mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-07 19:12:17 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
232d560cc4 | ||
|
|
b8b56584bd | ||
|
|
ce2daaf6c4 | ||
|
|
78d9e0bd2a | ||
|
|
55695ba06c | ||
|
|
ca3514d1d2 | ||
|
|
b2db3755d8 | ||
|
|
606c1895a9 | ||
|
|
968b12c4ac | ||
|
|
0f3cbaec3d | ||
|
|
2614efe601 | ||
|
|
eb6bd646c8 | ||
|
|
65147870fd | ||
|
|
586f0bba68 | ||
|
|
c4b26d70b5 | ||
|
|
8cbc58f775 | ||
|
|
8740cc7685 | ||
|
|
506c39896a | ||
|
|
9db34fd90e | ||
|
|
ae4353cc4b | ||
|
|
bde58fbf60 | ||
|
|
01b399e4a6 | ||
|
|
6235ffd0dc | ||
|
|
4504276563 | ||
|
|
96da39923d | ||
|
|
8633650f82 | ||
|
|
182091c21a | ||
|
|
7bed9ad7b8 | ||
|
|
7eb4238efd | ||
|
|
ea74c8885f | ||
|
|
7cdf463e4e | ||
|
|
850f910b96 | ||
|
|
4492696e3d | ||
|
|
dc74020f2d |
@@ -5,6 +5,7 @@ APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
SCOUT_DRIVER=tntsearch
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
@@ -44,3 +45,6 @@ PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
PASSPORT_CLIENT_ID=
|
||||
PASSPORT_CLIENT_SECRET=
|
||||
|
||||
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/vue-filemanager-laravel.iml" filepath="$PROJECT_DIR$/.idea/vue-filemanager-laravel.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
128
.idea/php.xml
generated
128
.idea/php.xml
generated
@@ -1,128 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PhpIncludePathManager">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
|
||||
<path value="$PROJECT_DIR$/vendor/gabrielelana/byte-units" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
|
||||
<path value="$PROJECT_DIR$/vendor/asm89/stack-cors" />
|
||||
<path value="$PROJECT_DIR$/vendor/psy/psysh" />
|
||||
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
|
||||
<path value="$PROJECT_DIR$/vendor/mockery/mockery" />
|
||||
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
|
||||
<path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
|
||||
<path value="$PROJECT_DIR$/vendor/intervention/image" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
|
||||
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
|
||||
<path value="$PROJECT_DIR$/vendor/barryvdh/laravel-cors" />
|
||||
<path value="$PROJECT_DIR$/vendor/opis/closure" />
|
||||
<path value="$PROJECT_DIR$/vendor/paragonie/random_compat" />
|
||||
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
|
||||
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/teamtnt/laravel-scout-tntsearch-driver" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
|
||||
<path value="$PROJECT_DIR$/vendor/teamtnt/tntsearch" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
|
||||
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||
<path value="$PROJECT_DIR$/vendor/fideloper/proxy" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-token-stream" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
|
||||
<path value="$PROJECT_DIR$/vendor/dnoegel/php-xdg-base-dir" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/ramsey/uuid" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/flysystem" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php72" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/debug" />
|
||||
<path value="$PROJECT_DIR$/vendor/erusev/parsedown" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-iconv" />
|
||||
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/process" />
|
||||
<path value="$PROJECT_DIR$/vendor/swiftmailer/swiftmailer" />
|
||||
<path value="$PROJECT_DIR$/vendor/fzaninotto/faker" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpspec/prophecy" />
|
||||
<path value="$PROJECT_DIR$/vendor/askedio/laravel-soft-cascade" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/framework" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/scout" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/tinker" />
|
||||
<path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
|
||||
<path value="$PROJECT_DIR$/vendor/dragonmantank/cron-expression" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
|
||||
<path value="$PROJECT_DIR$/vendor/beyondcode/laravel-dump-server" />
|
||||
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
|
||||
<path value="$PROJECT_DIR$/vendor/nunomaduro/collision" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
|
||||
<path value="$PROJECT_DIR$/vendor/tijsverkoyen/css-to-inline-styles" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
|
||||
<path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
|
||||
<path value="$PROJECT_DIR$/vendor/filp/whoops" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
|
||||
<path value="$PROJECT_DIR$/vendor/jakub-onderka/php-console-color" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/container" />
|
||||
<path value="$PROJECT_DIR$/vendor/jakub-onderka/php-console-highlighter" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/log" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
|
||||
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
|
||||
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/passport" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/event" />
|
||||
<path value="$PROJECT_DIR$/vendor/facade/ignition" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/oauth2-server" />
|
||||
<path value="$PROJECT_DIR$/vendor/facade/flare-client-php" />
|
||||
<path value="$PROJECT_DIR$/vendor/defuse/php-encryption" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpseclib/phpseclib" />
|
||||
<path value="$PROJECT_DIR$/vendor/laminas/laminas-zendframework-bridge" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
|
||||
<path value="$PROJECT_DIR$/vendor/laminas/laminas-diactoros" />
|
||||
<path value="$PROJECT_DIR$/vendor/firebase/php-jwt" />
|
||||
<path value="$PROJECT_DIR$/vendor/fruitcake/laravel-cors" />
|
||||
<path value="$PROJECT_DIR$/vendor/scrivo/highlight.php" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
|
||||
<path value="$PROJECT_DIR$/vendor/lcobucci/jwt" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/psr-http-message-bridge" />
|
||||
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
|
||||
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
|
||||
<path value="$PROJECT_DIR$/vendor/facade/ignition-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/commonmark" />
|
||||
<path value="$PROJECT_DIR$/vendor/php-http/message-factory" />
|
||||
<path value="$PROJECT_DIR$/vendor/nyholm/psr7" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="7.2" />
|
||||
<component name="PhpUnit">
|
||||
<phpunit_settings>
|
||||
<PhpUnitSettings load_method="CUSTOM_LOADER" configuration_file_path="$PROJECT_DIR$/phpunit.xml" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" use_configuration_file="true" />
|
||||
</phpunit_settings>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
34
.idea/vue-filemanager-laravel.iml
generated
34
.idea/vue-filemanager-laravel.iml
generated
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/app" isTestSource="false" packagePrefix="App\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/defuse/php-encryption" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/flare-client-php" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/firebase/php-jwt" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/fruitcake/laravel-cors" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/laminas/laminas-diactoros" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/laminas/laminas-zendframework-bridge" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/passport" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/lcobucci/jwt" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/league/commonmark" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/league/event" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/league/oauth2-server" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/nyholm/psr7" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/php-http/message-factory" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpseclib/phpseclib" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-factory" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/scrivo/highlight.php" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/type" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/error-handler" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/psr-http-message-bridge" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
4
.idea/watcherTasks.xml
generated
4
.idea/watcherTasks.xml
generated
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions" suppressed-tasks="SCSS" />
|
||||
</project>
|
||||
739
.idea/workspace.xml
generated
739
.idea/workspace.xml
generated
@@ -1,739 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="6ba7f65e-b845-4413-bbbb-cad4b4fb5f38" name="Default Changelist" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.editorconfig" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/php.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/php.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/vue-filemanager-laravel.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/vue-filemanager-laravel.iml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/FileManagerFile.php" beforeDir="false" afterPath="$PROJECT_DIR$/app/FileManagerFile.php" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/FileManagerFolder.php" beforeDir="false" afterPath="$PROJECT_DIR$/app/FileManagerFolder.php" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Http/Controllers/FileManagerController.php" beforeDir="false" afterPath="$PROJECT_DIR$/app/Http/Controllers/FileManagerController.php" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/composer.lock" beforeDir="false" afterPath="$PROJECT_DIR$/composer.lock" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/config/vuefilemanager.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/vuefilemanager.php" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/public/css/app.css" beforeDir="false" afterPath="$PROJECT_DIR$/public/css/app.css" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/public/js/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/public/js/main.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/public/mix-manifest.json" beforeDir="false" afterPath="$PROJECT_DIR$/public/mix-manifest.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManager.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManager.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Auth.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Auth.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/Alert.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/Alert.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ContextMenu.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ContextMenu.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/DesktopToolbar.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/DesktopToolbar.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FileInfoPanel.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FileInfoPanel.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FileItemList.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FileItemList.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FilesContainer.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FilesContainer.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileActionButton.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileActionButton.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileActionButtonUpload.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileActionButtonUpload.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileOptionList.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileOptionList.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileToolbar.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/MobileToolbar.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ToolbarButton.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ToolbarButton.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ToolbarButtonUpload.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ToolbarButtonUpload.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Others/PageHeader.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Others/PageHeader.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Others/TextLabel.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Others/TextLabel.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar/StorageSize.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar/StorageSize.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar/UserHeadline.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar/UserHeadline.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/UserSettings.vue" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/UserSettings.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/components/router.js" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/helpers.js" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/helpers.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/store/modules/filesView.js" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/store/modules/filesView.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/js/store/modules/userAuth.js" beforeDir="false" afterPath="$PROJECT_DIR$/resources/js/store/modules/userAuth.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/sass/vue-file-manager/_forms.scss" beforeDir="false" afterPath="$PROJECT_DIR$/resources/sass/vue-file-manager/_forms.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/resources/views/index.blade.php" beforeDir="false" afterPath="$PROJECT_DIR$/resources/views/index.blade.php" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/routes/api.php" beforeDir="false" afterPath="$PROJECT_DIR$/routes/api.php" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/webpack.mix.js" beforeDir="false" afterPath="$PROJECT_DIR$/webpack.mix.js" afterDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ComposerSettings" doNotAsk="true" synchronizationState="SYNCHRONIZE">
|
||||
<pharConfigPath>$PROJECT_DIR$/composer.json</pharConfigPath>
|
||||
<execution>
|
||||
<executable />
|
||||
</execution>
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Auth.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="201">
|
||||
<caret line="516" column="13" selection-start-line="516" selection-start-column="13" selection-end-line="516" selection-end-column="13" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/resources/sass/vue-file-manager/_forms.scss">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="112">
|
||||
<caret line="28" column="26" lean-forward="true" selection-start-line="28" selection-start-column="26" selection-end-line="28" selection-end-column="26" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>SET_AUTHORIZED</find>
|
||||
<find>error.data</find>
|
||||
<find>SET_START_DIREC</find>
|
||||
<find>Nunito:400</find>
|
||||
<find>context</find>
|
||||
<find>token</find>
|
||||
<find>cookie</find>
|
||||
<find>getAppData</find>
|
||||
<find>SET_AUT</find>
|
||||
<find>PublicCloud</find>
|
||||
<find>Illuminate\Http\Response</find>
|
||||
<find>$updateText</find>
|
||||
<find>...map</find>
|
||||
<find>...mapGetters</find>
|
||||
<find>access_token</find>
|
||||
<find>user_account_capacity</find>
|
||||
<find>'bo</find>
|
||||
<find>SET_CURRENT</find>
|
||||
<find>logOut</find>
|
||||
<find>255</find>
|
||||
<find>_forms</find>
|
||||
<find>limit</find>
|
||||
<find>max_file_uploads</find>
|
||||
<find>post_max_size</find>
|
||||
<find>uploadFiles</find>
|
||||
<find>whereIn</find>
|
||||
<find>trash</find>
|
||||
<find>you exceed your storage</find>
|
||||
<find>deleted_files</find>
|
||||
<find>trashed_files</find>
|
||||
</findStrings>
|
||||
</component>
|
||||
<component name="FrameworkCommandLineHistory">
|
||||
<commandsHistory>
|
||||
<command text="npm update" />
|
||||
<command text="npm run prod" />
|
||||
<command text="npm update" />
|
||||
<command text="npm run prod" />
|
||||
<command text="npm update" />
|
||||
<command text="npm run prod" />
|
||||
<command text="npm remove sass-loader" />
|
||||
<command text="npm update" />
|
||||
<command text="npm rebuild" />
|
||||
<command text="npm run prod" />
|
||||
<command text="npm run hot" />
|
||||
<command text="php artisan make:controller AppFunctionsController" />
|
||||
<command text="php artisan dump-autoload" />
|
||||
<command text="composer dump-autoload" />
|
||||
<command text="php artisan serve" />
|
||||
<command text="composer update" />
|
||||
<command text="npm run prod" />
|
||||
<command text="npm run hot" />
|
||||
<command text="php artisan serve" />
|
||||
<command text="npm run hot" />
|
||||
<command text="php artisan serve" />
|
||||
<command text="npm run hot" />
|
||||
<command text="npm run prod" />
|
||||
<command text="npm run hot" />
|
||||
<command text="npm run prod" />
|
||||
</commandsHistory>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="mock:///Dummy.txt" root0="SKIP_INSPECTION" />
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/package.json" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Middleware/Authenticate.php" />
|
||||
<option value="$PROJECT_DIR$/resources/js/bootstrap.js" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Middleware/CookieAuth.php" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Kernel.php" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Middleware/EncryptCookies.php" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Controllers/PrivateCLoud/AuthController.php" />
|
||||
<option value="$PROJECT_DIR$/resources/js/main.js" />
|
||||
<option value="$PROJECT_DIR$/resources/js/store/modules/app.js" />
|
||||
<option value="$PROJECT_DIR$/.gitignore" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Controllers/PrivateCLoud/FileManagerController.php" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Controllers/PrivateCLoud/UserAccountController.php" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Controllers/AppFunctionsController.php" />
|
||||
<option value="$PROJECT_DIR$/resources/sass/app.scss" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Others/UserImageInput.vue" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Controllers/Auth/AuthController.php" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar/StorageSize.vue" />
|
||||
<option value="$PROJECT_DIR$/app/Http/helpers.php" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar/UserHeadline.vue" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Controllers/UserAccountController.php" />
|
||||
<option value="$PROJECT_DIR$/routes/web.php" />
|
||||
<option value="$PROJECT_DIR$/resources/js/store/modules/userAuth.js" />
|
||||
<option value="$PROJECT_DIR$/resources/js/App.vue" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManager.vue" />
|
||||
<option value="$PROJECT_DIR$/.env" />
|
||||
<option value="$USER_HOME$/Desktop/vue-file-manager-file-manager-127.0.0.111-03-2020" />
|
||||
<option value="<d768a9d2-ae0a-4b11-a436-c632a530c3ce>/var/www/devvuefilemanagerlaravel.hi5ve.digital/.env" />
|
||||
<option value="<d768a9d2-ae0a-4b11-a436-c632a530c3ce>/etc/apache2/sites-available/devvuefilemanager.hi5ve.digital.conf" />
|
||||
<option value="<d768a9d2-ae0a-4b11-a436-c632a530c3ce>/var/www/devvuefilemanager.hi5ve.digital/.env" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/UserSettings.vue" />
|
||||
<option value="$PROJECT_DIR$/app/FileManagerFile.php" />
|
||||
<option value="$PROJECT_DIR$/routes/api.php" />
|
||||
<option value="<d768a9d2-ae0a-4b11-a436-c632a530c3ce>/var/www/devvuefilemanager.hi5ve.digital/config/vuefilemanager.php" />
|
||||
<option value="<d768a9d2-ae0a-4b11-a436-c632a530c3ce>/var/www/devvuefilemanager.hi5ve.digital/public/info.php" />
|
||||
<option value="<d768a9d2-ae0a-4b11-a436-c632a530c3ce>/etc/php/7.3/apache2/php.ini" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar.vue" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/Alert.vue" />
|
||||
<option value="$PROJECT_DIR$/app/Http/Controllers/FileManagerController.php" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FileItemList.vue" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ToolbarButtonUpload.vue" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Others/TextLabel.vue" />
|
||||
<option value="$PROJECT_DIR$/resources/js/helpers.js" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView.vue" />
|
||||
<option value="$PROJECT_DIR$/webpack.mix.js" />
|
||||
<option value="$PROJECT_DIR$/public/mix-manifest.json" />
|
||||
<option value="$PROJECT_DIR$/resources/views/index.blade.php" />
|
||||
<option value="$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Auth.vue" />
|
||||
<option value="$PROJECT_DIR$/resources/js/store/modules/filesView.js" />
|
||||
<option value="$PROJECT_DIR$/app/FileManagerFolder.php" />
|
||||
<option value="$PROJECT_DIR$/config/vuefilemanager.php" />
|
||||
<option value="$PROJECT_DIR$/resources/sass/vue-file-manager/_forms.scss" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="PhpWorkspaceProjectConfiguration">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
|
||||
<path value="$PROJECT_DIR$/vendor/gabrielelana/byte-units" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
|
||||
<path value="$PROJECT_DIR$/vendor/asm89/stack-cors" />
|
||||
<path value="$PROJECT_DIR$/vendor/psy/psysh" />
|
||||
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
|
||||
<path value="$PROJECT_DIR$/vendor/mockery/mockery" />
|
||||
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
|
||||
<path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
|
||||
<path value="$PROJECT_DIR$/vendor/intervention/image" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
|
||||
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
|
||||
<path value="$PROJECT_DIR$/vendor/barryvdh/laravel-cors" />
|
||||
<path value="$PROJECT_DIR$/vendor/opis/closure" />
|
||||
<path value="$PROJECT_DIR$/vendor/paragonie/random_compat" />
|
||||
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
|
||||
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/teamtnt/laravel-scout-tntsearch-driver" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
|
||||
<path value="$PROJECT_DIR$/vendor/teamtnt/tntsearch" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
|
||||
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||
<path value="$PROJECT_DIR$/vendor/fideloper/proxy" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-token-stream" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
|
||||
<path value="$PROJECT_DIR$/vendor/dnoegel/php-xdg-base-dir" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/ramsey/uuid" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/flysystem" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php72" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/debug" />
|
||||
<path value="$PROJECT_DIR$/vendor/erusev/parsedown" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-iconv" />
|
||||
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/process" />
|
||||
<path value="$PROJECT_DIR$/vendor/swiftmailer/swiftmailer" />
|
||||
<path value="$PROJECT_DIR$/vendor/fzaninotto/faker" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpspec/prophecy" />
|
||||
<path value="$PROJECT_DIR$/vendor/askedio/laravel-soft-cascade" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/framework" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/scout" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/tinker" />
|
||||
<path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
|
||||
<path value="$PROJECT_DIR$/vendor/dragonmantank/cron-expression" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
|
||||
<path value="$PROJECT_DIR$/vendor/beyondcode/laravel-dump-server" />
|
||||
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
|
||||
<path value="$PROJECT_DIR$/vendor/nunomaduro/collision" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
|
||||
<path value="$PROJECT_DIR$/vendor/tijsverkoyen/css-to-inline-styles" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
|
||||
<path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
|
||||
<path value="$PROJECT_DIR$/vendor/filp/whoops" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
|
||||
<path value="$PROJECT_DIR$/vendor/jakub-onderka/php-console-color" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/container" />
|
||||
<path value="$PROJECT_DIR$/vendor/jakub-onderka/php-console-highlighter" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/log" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
|
||||
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
|
||||
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
|
||||
<path value="$PROJECT_DIR$/vendor/laravel/passport" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/event" />
|
||||
<path value="$PROJECT_DIR$/vendor/facade/ignition" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/oauth2-server" />
|
||||
<path value="$PROJECT_DIR$/vendor/facade/flare-client-php" />
|
||||
<path value="$PROJECT_DIR$/vendor/defuse/php-encryption" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpseclib/phpseclib" />
|
||||
<path value="$PROJECT_DIR$/vendor/laminas/laminas-zendframework-bridge" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
|
||||
<path value="$PROJECT_DIR$/vendor/laminas/laminas-diactoros" />
|
||||
<path value="$PROJECT_DIR$/vendor/firebase/php-jwt" />
|
||||
<path value="$PROJECT_DIR$/vendor/fruitcake/laravel-cors" />
|
||||
<path value="$PROJECT_DIR$/vendor/scrivo/highlight.php" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
|
||||
<path value="$PROJECT_DIR$/vendor/lcobucci/jwt" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/psr-http-message-bridge" />
|
||||
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
|
||||
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
|
||||
<path value="$PROJECT_DIR$/vendor/facade/ignition-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/league/commonmark" />
|
||||
<path value="$PROJECT_DIR$/vendor/php-http/message-factory" />
|
||||
<path value="$PROJECT_DIR$/vendor/nyholm/psr7" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" fullScreen="true">
|
||||
<option name="width" value="1680" />
|
||||
<option name="height" value="1050" />
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
||||
<ConfirmationsSetting value="2" id="Add" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator proportions="" version="1">
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="vue-filemanager-laravel-v1.1" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="vue-filemanager-laravel-v1.1" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="true" />
|
||||
<property name="WebServerToolWindowPanel.toolwindow.highlight.mappings" value="true" />
|
||||
<property name="WebServerToolWindowPanel.toolwindow.highlight.symlinks" value="true" />
|
||||
<property name="WebServerToolWindowPanel.toolwindow.show.date" value="false" />
|
||||
<property name="WebServerToolWindowPanel.toolwindow.show.permissions" value="false" />
|
||||
<property name="WebServerToolWindowPanel.toolwindow.show.size" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/resources/sass" />
|
||||
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
||||
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
|
||||
<property name="nodejs_package_manager_path" value="npm" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/app/Http/Controllers" />
|
||||
<recent name="$PROJECT_DIR$/resources/sass/vue-file-manager" />
|
||||
<recent name="$PROJECT_DIR$/app/Http/Controllers/PrivateCLoud" />
|
||||
</key>
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/resources/sass" />
|
||||
<recent name="$PROJECT_DIR$/resources/js" />
|
||||
<recent name="$PROJECT_DIR$/public/assets/images" />
|
||||
<recent name="$PROJECT_DIR$/app/Http/Controllers/PublicCloud" />
|
||||
<recent name="$PROJECT_DIR$/app" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="phpunit.xml" type="PHPUnitRunConfigurationType" factoryName="PHPUnit">
|
||||
<TestRunner scope="XML" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SvnConfiguration">
|
||||
<configuration />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="6ba7f65e-b845-4413-bbbb-cad4b4fb5f38" name="Default Changelist" comment="" />
|
||||
<created>1582538406416</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1582538406416</updated>
|
||||
<workItem from="1582538408226" duration="28590000" />
|
||||
<workItem from="1583169038847" duration="49277000" />
|
||||
<workItem from="1583771973016" duration="47540000" />
|
||||
<workItem from="1584014365621" duration="499000" />
|
||||
<workItem from="1584201902438" duration="1297000" />
|
||||
<workItem from="1584205890781" duration="1931000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TimeTrackingManager">
|
||||
<option name="totallyTimeSpent" value="129134000" />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="0" y="0" width="1680" height="1050" extended-state="0" />
|
||||
<layout>
|
||||
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.15654762" />
|
||||
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
|
||||
<window_info id="npm" order="2" side_tool="true" />
|
||||
<window_info id="Favorites" order="3" side_tool="true" />
|
||||
<window_info anchor="bottom" id="Message" order="0" />
|
||||
<window_info anchor="bottom" id="Find" order="1" />
|
||||
<window_info anchor="bottom" id="Run" order="2" weight="0.3295238" />
|
||||
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
|
||||
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
||||
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||
<window_info anchor="bottom" id="TODO" order="6" />
|
||||
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
|
||||
<window_info anchor="bottom" id="Version Control" order="8" />
|
||||
<window_info anchor="bottom" id="Database Changes" order="9" />
|
||||
<window_info active="true" anchor="bottom" id="Command Line Tools Console" order="10" visible="true" weight="0.36761904" />
|
||||
<window_info anchor="bottom" id="Terminal" order="11" weight="0.3295238" />
|
||||
<window_info anchor="bottom" id="Event Log" order="12" side_tool="true" />
|
||||
<window_info anchor="bottom" id="File Transfer" order="13" weight="0.3295238" />
|
||||
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
|
||||
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
|
||||
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
|
||||
<window_info anchor="right" id="Database" order="3" />
|
||||
<window_info anchor="right" id="Remote Host" order="4" weight="0.23869048" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-RlTVKdTenHVQeDuC-8f8b71f93d874c58899eae34ff855b91.jpg.1280x0_q85.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-qu7zENEPpyXacK9u-8acb7489e4354e9fa12b786f4f1014b3.jpg.1280x0_q85.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-PwOYrH3X4Q5MFNnJ-b828ce5c1d014deab79c6b1ac8dd5500.jpg.1280x0_q85.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-PeK8nBe7vKFR2DXN-8480033d08b555735bcc1df441eeec0f.png">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-Ogjq9EIILgeojKDb-nf88xyvvCWOJHY93-kitchen-island.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-NfLjyaaboBPCGi3X-7bec4e11b047456780d83011701a662c.jpg.1280x0_q85.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-md1FYpic11mXzsMH-59352395_2290695347810363_751927439731487941_n.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-lnh7N5vgH74DhOOh-57bad2c20c758f20b83b2344212a2a93.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-ddGQjKsXe6smj3Jx-7bec4e11b047456780d83011701a662c.jpg.1280x0_q85.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-eIXPHBrXEjqxydte-d5410c8079e3a3970303779305d11048.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-Fg3cXWFgEn6Cmt5M-6f5362be8aca06dc4ea234865ac49736.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-fNx1iGh1lpGyS66P-af0c68fb4d3b82da011ca4b0c18c8a65.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-Gv6TX9lZl8TZ5kCK-8f8b71f93d874c58899eae34ff855b91.jpg.1280x0_q85.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-HlK34TY0sfw4lDk3-nf88xyvvCWOJHY93-kitchen-island.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-i2BdCpXqXyMcS5oB-ea7afab3993a45c3a88ee7eb9ce42a8e.jpg.1280x0_q85.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-IseiNdZqCg7dQRD0-ItWorksOnMyMachine.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-Jaupegd57IHxsSGE-57bad2c20c758f20b83b2344212a2a93.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/storage/app/file-manager/thumbnail-JVdvcCD7WcFNG6MF-ViewOfElephantinWater.jpg">
|
||||
<provider selected="true" editor-type-id="images" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Sidebar.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="363">
|
||||
<caret line="194" column="9" selection-start-line="194" selection-start-column="9" selection-end-line="194" selection-end-column="9" />
|
||||
<folding>
|
||||
<element signature="n#div#0;n#div#0;n#transition#0;n#template#0;n#!!top" />
|
||||
<element signature="e#3246#3349#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/Alert.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="713">
|
||||
<caret line="89" column="17" selection-start-line="89" selection-start-column="17" selection-end-line="89" selection-end-column="17" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/app/Http/helpers.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="330">
|
||||
<caret line="116" column="22" selection-start-line="116" selection-start-column="9" selection-end-line="116" selection-end-column="22" />
|
||||
<folding>
|
||||
<element signature="n#store_avatar#0;n#!!top" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/helpers.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="320">
|
||||
<caret line="148" column="38" selection-start-line="148" selection-start-column="22" selection-end-line="148" selection-end-column="38" />
|
||||
<folding>
|
||||
<element signature="e#0#33#0" expanded="true" />
|
||||
<element signature="e#201#287#0" />
|
||||
<element signature="e#730#1219#0" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ToolbarButtonUpload.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="280">
|
||||
<caret line="10" column="60" selection-start-line="10" selection-start-column="60" selection-end-line="10" selection-end-column="60" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/FileItemList.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="448">
|
||||
<caret line="47" column="77" selection-start-line="47" selection-start-column="59" selection-end-line="47" selection-end-column="77" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Others/TextLabel.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="672">
|
||||
<caret line="24" selection-start-line="21" selection-start-column="27" selection-end-line="24" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.editorconfig">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.env">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManager.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="560">
|
||||
<caret line="20" column="26" selection-start-line="20" selection-start-column="17" selection-end-line="20" selection-end-column="26" />
|
||||
<folding>
|
||||
<element signature="e#618#695#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="187">
|
||||
<caret line="57" column="40" selection-start-line="57" selection-start-column="40" selection-end-line="57" selection-end-column="40" />
|
||||
<folding>
|
||||
<element signature="e#314#409#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/public/mix-manifest.json">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="56">
|
||||
<caret line="2" column="35" selection-start-line="2" selection-start-column="35" selection-end-line="2" selection-end-column="35" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/DemoPageComponents/MobileMenu.vue">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/main.js">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/App.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="56">
|
||||
<caret line="2" column="31" lean-forward="true" selection-start-line="2" selection-start-column="31" selection-end-line="2" selection-end-column="31" />
|
||||
<folding>
|
||||
<element signature="n#style#0;n#VueFileManager#0;n#div#0;n#template#0;n#!!top" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/webpack.mix.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="476">
|
||||
<caret line="17" column="14" lean-forward="true" selection-start-line="17" selection-start-column="14" selection-end-line="17" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.styleci.yml">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/config/auth.php">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/store/modules/filesView.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="594">
|
||||
<caret line="185" column="48" selection-start-line="185" selection-start-column="12" selection-end-line="185" selection-end-column="48" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/store/modules/userAuth.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="2734">
|
||||
<caret line="101" column="4" selection-start-line="101" selection-start-column="4" selection-end-line="101" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/FilesView/ContextMenu.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="442">
|
||||
<caret line="50" column="51" selection-start-line="50" selection-start-column="51" selection-end-line="50" selection-end-column="51" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/app/Http/Controllers/AppFunctionsController.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-186">
|
||||
<caret line="8" column="6" selection-start-line="8" selection-start-column="6" selection-end-line="8" selection-end-column="6" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/app/FileManagerFolder.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="3342">
|
||||
<caret line="120" column="5" selection-start-line="120" selection-start-column="5" selection-end-line="120" selection-end-column="5" />
|
||||
<folding>
|
||||
<element signature="e#23#41#0#PHP" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/app/FileManagerFile.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-1682">
|
||||
<caret line="13" column="6" selection-start-line="13" selection-start-column="6" selection-end-line="13" selection-end-column="6" />
|
||||
<folding>
|
||||
<element signature="e#23#44#0#PHP" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/app/Http/Controllers/Auth/AuthController.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-2678">
|
||||
<caret line="19" column="6" selection-start-line="19" selection-start-column="6" selection-end-line="19" selection-end-column="6" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/app/Http/Controllers/UserAccountController.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-3070">
|
||||
<caret line="14" column="6" selection-start-line="14" selection-start-column="6" selection-end-line="14" selection-end-column="6" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/app/Http/Controllers/FileManagerController.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-11946">
|
||||
<caret line="164" column="49" lean-forward="true" selection-start-line="164" selection-start-column="49" selection-end-line="164" selection-end-column="49" />
|
||||
<folding>
|
||||
<element signature="e#40#67#0#PHP" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/views/index.blade.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="326">
|
||||
<caret line="26" column="46" selection-start-line="26" selection-start-column="46" selection-end-line="26" selection-end-column="46" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/config/vuefilemanager.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="308">
|
||||
<caret line="11" column="35" selection-start-line="11" selection-start-column="35" selection-end-line="11" selection-end-column="35" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/routes/web.php">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/routes/api.php">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-40">
|
||||
<caret line="45" column="37" selection-start-line="45" selection-start-column="37" selection-end-line="45" selection-end-column="37" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/js/components/VueFileManagerComponents/Auth.vue">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="201">
|
||||
<caret line="516" column="13" selection-start-line="516" selection-start-column="13" selection-end-line="516" selection-end-column="13" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/resources/sass/vue-file-manager/_forms.scss">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="112">
|
||||
<caret line="28" column="26" lean-forward="true" selection-start-line="28" selection-start-column="26" selection-end-line="28" selection-end-column="26" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
||||
1317
.phpstorm.meta.php
Normal file
1317
.phpstorm.meta.php
Normal file
File diff suppressed because it is too large
Load Diff
110
README.md
110
README.md
@@ -1,78 +1,48 @@
|
||||
<p align="center"><img src="https://res.cloudinary.com/dtfbvvkyp/image/upload/v1566331377/laravel-logolockup-cmyk-red.svg" width="400"></p>
|
||||
### Documentation
|
||||
[Read online documentation](https://vuefilemanager.com/docs/)
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/d/total.svg" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/v/stable.svg" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/license.svg" alt="License"></a>
|
||||
</p>
|
||||
### Installation setup
|
||||
|
||||
## About Laravel
|
||||
Run these commands to install vendors:
|
||||
```
|
||||
composer install
|
||||
```
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
|
||||
Setup your database in .env and run this command:
|
||||
```
|
||||
php artisan setup:prod
|
||||
```
|
||||
|
||||
- [Simple, fast routing engine](https://laravel.com/docs/routing).
|
||||
- [Powerful dependency injection container](https://laravel.com/docs/container).
|
||||
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
|
||||
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
|
||||
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
|
||||
- [Robust background job processing](https://laravel.com/docs/queues).
|
||||
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
|
||||
It automatically:
|
||||
* Migrate database
|
||||
* Generate Application key
|
||||
* Create Passport Encryption keys
|
||||
* Create Password grant client
|
||||
* Create Personal access client
|
||||
|
||||
Laravel is accessible, powerful, and provides tools required for large, robust applications.
|
||||
Then, copy generated password grant client `Client ID`, `Client secret` and paste it to .env files here:
|
||||
```
|
||||
PASSPORT_CLIENT_ID=<your_passport_client_id>
|
||||
PASSPORT_CLIENT_SECRET=<your_passport_client_secret>
|
||||
```
|
||||
For sending forgoten password request via email, fill your mail driver in .env
|
||||
|
||||
## Learning Laravel
|
||||
### Run Application
|
||||
To start server on your localhost, run this command
|
||||
```
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
|
||||
To compiles and hot-reloads for development, run this command
|
||||
```
|
||||
npm run hot
|
||||
```
|
||||
|
||||
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
|
||||
|
||||
## Laravel Sponsors
|
||||
|
||||
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
|
||||
|
||||
- **[Vehikl](https://vehikl.com/)**
|
||||
- **[Tighten Co.](https://tighten.co)**
|
||||
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
|
||||
- **[64 Robots](https://64robots.com)**
|
||||
- **[Cubet Techno Labs](https://cubettech.com)**
|
||||
- **[Cyber-Duck](https://cyber-duck.co.uk)**
|
||||
- **[British Software Development](https://www.britishsoftware.co)**
|
||||
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
|
||||
- **[DevSquad](https://devsquad.com)**
|
||||
- [UserInsights](https://userinsights.com)
|
||||
- [Fragrantica](https://www.fragrantica.com)
|
||||
- [SOFTonSOFA](https://softonsofa.com/)
|
||||
- [User10](https://user10.com)
|
||||
- [Soumettre.fr](https://soumettre.fr/)
|
||||
- [CodeBrisk](https://codebrisk.com)
|
||||
- [1Forge](https://1forge.com)
|
||||
- [TECPRESSO](https://tecpresso.co.jp/)
|
||||
- [Runtime Converter](http://runtimeconverter.com/)
|
||||
- [WebL'Agence](https://weblagence.com/)
|
||||
- [Invoice Ninja](https://www.invoiceninja.com)
|
||||
- [iMi digital](https://www.imi-digital.de/)
|
||||
- [Earthlink](https://www.earthlink.ro/)
|
||||
- [Steadfast Collective](https://steadfastcollective.com/)
|
||||
- [We Are The Robots Inc.](https://watr.mx/)
|
||||
- [Understand.io](https://www.understand.io/)
|
||||
- [Abdel Elrafa](https://abdelelrafa.com)
|
||||
- [Hyper Host](https://hyper.host)
|
||||
- [Appoly](https://www.appoly.co.uk)
|
||||
- [OP.GG](https://op.gg)
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
|
||||
|
||||
## License
|
||||
|
||||
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
To compiles for production, run this command
|
||||
```
|
||||
npm run prod
|
||||
```
|
||||
That's all, happy coding! :tada: :tada: :tada:
|
||||
|
||||
18211
_ide_helper.php
Normal file
18211
_ide_helper.php
Normal file
File diff suppressed because it is too large
Load Diff
101
app/Console/Commands/SetupProductionEnvironment.php
Normal file
101
app/Console/Commands/SetupProductionEnvironment.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SetupProductionEnvironment extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'setup:prod';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Setting production environment';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('Setting up production environment');
|
||||
|
||||
$this->migrateDatabase();
|
||||
$this->generateKey();
|
||||
$this->createPassportKeys();
|
||||
$this->createPassportClientPassword();
|
||||
$this->createPassportClientPersonal();
|
||||
|
||||
$this->info('Everything is done, congratulations! 🥳🥳🥳');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database
|
||||
*/
|
||||
public function generateKey()
|
||||
{
|
||||
$this->call('key:generate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database
|
||||
*/
|
||||
public function migrateDatabase()
|
||||
{
|
||||
$this->call('migrate:fresh');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Passport Encryption keys
|
||||
*/
|
||||
public function createPassportKeys()
|
||||
{
|
||||
$this->call('passport:keys', [
|
||||
'--force' => true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Password grant client
|
||||
*/
|
||||
public function createPassportClientPassword()
|
||||
{
|
||||
$this->call('passport:client', [
|
||||
'--password' => true,
|
||||
'--name' => 'vuefilemanager',
|
||||
]);
|
||||
|
||||
$this->alert('Please copy these first password grant Client ID & Client secret above to your /.env file.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Personal access client
|
||||
*/
|
||||
public function createPassportClientPersonal()
|
||||
{
|
||||
$this->call('passport:client', [
|
||||
'--personal' => true,
|
||||
'--name' => 'shared',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Console\Commands\SetupProductionEnvironment;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
@@ -13,7 +14,7 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
//
|
||||
SetupProductionEnvironment::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,18 +3,61 @@
|
||||
namespace App;
|
||||
|
||||
use ByteUnits\Metric;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Scout\Searchable;
|
||||
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
|
||||
use \Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use \Askedio\SoftCascade\Traits\SoftCascadeTrait;
|
||||
|
||||
/**
|
||||
* App\FileManagerFile
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $user_id
|
||||
* @property int $unique_id
|
||||
* @property int $folder_id
|
||||
* @property string $thumbnail
|
||||
* @property string|null $name
|
||||
* @property string|null $basename
|
||||
* @property string|null $mimetype
|
||||
* @property string $filesize
|
||||
* @property string|null $type
|
||||
* @property string $user_scope
|
||||
* @property string $deleted_at
|
||||
* @property string $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\FileManagerFolder|null $folder
|
||||
* @property-read string $file_url
|
||||
* @property-read \App\FileManagerFolder $parent
|
||||
* @property-read \App\Share|null $shared
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereBasename($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereFilesize($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereFolderId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereMimetype($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereThumbnail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUniqueId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUserId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUserScope($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
|
||||
class FileManagerFile extends Model
|
||||
{
|
||||
use Searchable, SoftDeletes, SoftCascadeTrait;
|
||||
use Searchable, SoftDeletes;
|
||||
|
||||
public $public_access = null;
|
||||
|
||||
protected $guarded = [
|
||||
'id'
|
||||
@@ -24,6 +67,15 @@ class FileManagerFile extends Model
|
||||
'file_url'
|
||||
];
|
||||
|
||||
/**
|
||||
* Set routes with public access
|
||||
*
|
||||
* @param $token
|
||||
*/
|
||||
public function setPublicUrl($token) {
|
||||
$this->public_access = $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format created at date
|
||||
*
|
||||
@@ -31,7 +83,7 @@ class FileManagerFile extends Model
|
||||
*/
|
||||
public function getCreatedAtAttribute()
|
||||
{
|
||||
return Carbon::create($this->attributes['created_at'])->format('j M Y \a\t H:i');;
|
||||
return format_date($this->attributes['created_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,13 +95,12 @@ class FileManagerFile extends Model
|
||||
{
|
||||
if (! $this->attributes['deleted_at']) return null;
|
||||
|
||||
return Carbon::create($this->attributes['deleted_at'])->format('j M Y at H:i');
|
||||
return format_date($this->attributes['deleted_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format filesize
|
||||
* Format fileSize
|
||||
*
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function getFilesizeAttribute()
|
||||
@@ -60,23 +111,39 @@ class FileManagerFile extends Model
|
||||
/**
|
||||
* Format thumbnail url
|
||||
*
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function getThumbnailAttribute()
|
||||
{
|
||||
return $this->attributes['thumbnail'] ? route('thumbnail', ['name' => $this->attributes['thumbnail']]) : null;
|
||||
if ($this->attributes['thumbnail']) {
|
||||
|
||||
// Thumbnail route
|
||||
$route = route('thumbnail', ['name' => $this->attributes['thumbnail']]);
|
||||
|
||||
if ($this->public_access) {
|
||||
return $route . '/public/' . $this->public_access;
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format file url
|
||||
*
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function getFileUrlAttribute()
|
||||
{
|
||||
return route('file', ['name' => $this->attributes['basename']]);
|
||||
$route = route('file', ['name' => $this->attributes['basename']]);
|
||||
|
||||
if ($this->public_access) {
|
||||
return $route . '/public/' . $this->public_access;
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,4 +182,14 @@ class FileManagerFile extends Model
|
||||
{
|
||||
return $this->hasOne('App\FileManagerFolder', 'unique_id', 'folder_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sharing attributes
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function shared()
|
||||
{
|
||||
return $this->hasOne('App\Share', 'item_id', 'unique_id');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,20 +11,62 @@ use RecursiveArrayIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
|
||||
use \Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use \Askedio\SoftCascade\Traits\SoftCascadeTrait;
|
||||
|
||||
/**
|
||||
* App\FileManagerFolder
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $user_id
|
||||
* @property int $unique_id
|
||||
* @property int $parent_id
|
||||
* @property string|null $name
|
||||
* @property string|null $type
|
||||
* @property string $user_scope
|
||||
* @property string $deleted_at
|
||||
* @property string $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $children
|
||||
* @property-read int|null $children_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $files
|
||||
* @property-read int|null $files_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $folders
|
||||
* @property-read int|null $folders_count
|
||||
* @property-read int $items
|
||||
* @property-read int $trashed_items
|
||||
* @property-read \App\FileManagerFolder $parent
|
||||
* @property-read \App\Share|null $shared
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $trashed_children
|
||||
* @property-read int|null $trashed_children_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $trashed_files
|
||||
* @property-read int|null $trashed_files_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $trashed_folders
|
||||
* @property-read int|null $trashed_folders_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereParentId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUniqueId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUserId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUserScope($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class FileManagerFolder extends Model
|
||||
{
|
||||
use Searchable, SoftDeletes, SoftCascadeTrait;
|
||||
use Searchable, SoftDeletes;
|
||||
|
||||
protected $guarded = [
|
||||
'id'
|
||||
];
|
||||
|
||||
protected $softCascade = [
|
||||
'children', 'files'
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'items', 'trashed_items'
|
||||
];
|
||||
@@ -79,7 +121,7 @@ class FileManagerFolder extends Model
|
||||
*/
|
||||
public function getCreatedAtAttribute()
|
||||
{
|
||||
return Carbon::create($this->attributes['created_at'])->format('j M Y \a\t H:i');
|
||||
return format_date($this->attributes['created_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +133,7 @@ class FileManagerFolder extends Model
|
||||
{
|
||||
if (! $this->attributes['deleted_at']) return null;
|
||||
|
||||
return Carbon::create($this->attributes['deleted_at'])->format('j M Y \a\t H:i');
|
||||
return format_date($this->attributes['deleted_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +158,6 @@ class FileManagerFolder extends Model
|
||||
*/
|
||||
public function files()
|
||||
{
|
||||
|
||||
return $this->hasMany('App\FileManagerFile', 'folder_id', 'unique_id');
|
||||
}
|
||||
|
||||
@@ -171,6 +212,16 @@ class FileManagerFolder extends Model
|
||||
return $this->hasMany('App\FileManagerFolder', 'parent_id', 'unique_id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sharing attributes
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function shared()
|
||||
{
|
||||
return $this->hasOne('App\Share', 'item_id', 'unique_id');
|
||||
}
|
||||
|
||||
// Delete all folder childrens
|
||||
public static function boot()
|
||||
{
|
||||
@@ -178,9 +229,22 @@ class FileManagerFolder extends Model
|
||||
|
||||
static::deleting(function ($item) {
|
||||
|
||||
$item->children()->each(function($folder) {
|
||||
$folder->delete();
|
||||
});
|
||||
if ( $item->isForceDeleting() ) {
|
||||
|
||||
$item->trashed_children()->each(function($folder) {
|
||||
$folder->forceDelete();
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
$item->children()->each(function($folder) {
|
||||
$folder->delete();
|
||||
});
|
||||
|
||||
$item->files()->each(function($file) {
|
||||
$file->delete();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
static::restoring(function ($item) {
|
||||
@@ -196,4 +260,4 @@ class FileManagerFolder extends Model
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Response;
|
||||
|
||||
class AppFunctionsController extends Controller
|
||||
@@ -17,28 +18,4 @@ class AppFunctionsController extends Controller
|
||||
{
|
||||
return view("index");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file
|
||||
*
|
||||
* @param $filename
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_avatar($basename)
|
||||
{
|
||||
// Get file path
|
||||
$path = storage_path() . '/app/avatars/' . $basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!File::exists($path)) abort(404);
|
||||
|
||||
$file = File::get($path);
|
||||
$type = File::mimeType($path);
|
||||
|
||||
// Create response
|
||||
$response = Response::make($file, 200);
|
||||
$response->header("Content-Type", $type);
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,13 @@
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\ClientProfile;
|
||||
use App\Models\User\UserAttribute;
|
||||
use App\Models\User\UserNotificationSetting;
|
||||
use App\ProviderProfile;
|
||||
use App\Http\Requests\Auth\CheckAccountRequest;
|
||||
use App\User;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
@@ -26,12 +19,7 @@ class AuthController extends Controller
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function check_account(Request $request) {
|
||||
|
||||
// Validate request
|
||||
$request->validate([
|
||||
'email' => ['required', 'string', 'email'],
|
||||
]);
|
||||
public function check_account(CheckAccountRequest $request) {
|
||||
|
||||
// Get User
|
||||
$user = User::where('email', $request->input('email'))->select(['name', 'avatar'])->first();
|
||||
@@ -43,7 +31,7 @@ class AuthController extends Controller
|
||||
];
|
||||
|
||||
// Abort with 404, user not found
|
||||
return abort('404', 'We can\'t find a user with that e-mail address.');
|
||||
return abort('404', __('vuefilemanager.user_not_fount'));
|
||||
}
|
||||
/**
|
||||
* Login user
|
||||
@@ -59,7 +47,7 @@ class AuthController extends Controller
|
||||
|
||||
$data = json_decode($response->content(), true);
|
||||
|
||||
return response('Login Successfull!', 200)->cookie('token', $data['access_token'], 43200);
|
||||
return response('Login Successfull!', 200)->cookie('access_token', $data['access_token'], 43200);
|
||||
} else {
|
||||
|
||||
return $response;
|
||||
@@ -97,7 +85,7 @@ class AuthController extends Controller
|
||||
|
||||
$data = json_decode($response->content(), true);
|
||||
|
||||
return response('Register Successfull!', 200)->cookie('token', $data['access_token'], 43200);
|
||||
return response('Register Successfull!', 200)->cookie('access_token', $data['access_token'], 43200);
|
||||
} else {
|
||||
|
||||
return $response;
|
||||
@@ -111,6 +99,12 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo( Auth::id())) {
|
||||
return response('Logout successfull', 204)
|
||||
->cookie('access_token', '', -1);
|
||||
}
|
||||
|
||||
// Get user tokens and remove it
|
||||
auth()->user()->tokens()->each(function ($token) {
|
||||
|
||||
@@ -118,7 +112,8 @@ class AuthController extends Controller
|
||||
$token->delete();
|
||||
});
|
||||
|
||||
return response('Logout successfull', 200)->cookie('token', '', -1);
|
||||
return response('Logout successfull', 204)
|
||||
->cookie('access_token', '', -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +123,7 @@ class AuthController extends Controller
|
||||
* @param string $provider
|
||||
* @return Request
|
||||
*/
|
||||
private static function make_request(Request $request)
|
||||
private static function make_request($request)
|
||||
{
|
||||
$request->request->add([
|
||||
'grant_type' => 'password',
|
||||
@@ -136,7 +131,7 @@ class AuthController extends Controller
|
||||
'client_secret' => config('services.passport.client_secret'),
|
||||
'username' => $request->email,
|
||||
'password' => $request->password,
|
||||
'scope' => '',
|
||||
'scope' => 'master',
|
||||
]);
|
||||
|
||||
return Request::create(url('/oauth/token'), 'POST', $request->all());
|
||||
|
||||
232
app/Http/Controllers/FileAccessController.php
Normal file
232
app/Http/Controllers/FileAccessController.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Tools\Guardian;
|
||||
use App\Share;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Http\Request;
|
||||
use App\FileManagerFile;
|
||||
use Illuminate\Support\Str;
|
||||
use Response;
|
||||
|
||||
class FileAccessController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get avatar
|
||||
*
|
||||
* @param $basename
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_avatar($basename)
|
||||
{
|
||||
// Get file path
|
||||
$path = storage_path() . '/app/avatars/' . $basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!File::exists($path)) abort(404);
|
||||
|
||||
$file = File::get($path);
|
||||
$type = File::mimeType($path);
|
||||
|
||||
// Create response
|
||||
$response = Response::make($file, 200);
|
||||
$response->header("Content-Type", $type);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $filename
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_file(Request $request, $filename)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('basename', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check user permission
|
||||
if ( ! $request->user()->tokenCan('master') ) {
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to file
|
||||
$this->check_file_access($shared, $file);
|
||||
}
|
||||
|
||||
return $this->download_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file public
|
||||
*
|
||||
* @param $filename
|
||||
* @param $token
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_file_public($filename, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if shared is protected
|
||||
if ($shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('basename', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check file access
|
||||
$this->check_file_access($shared, $file);
|
||||
|
||||
return $this->download_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image thumbnail
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $filename
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_thumbnail(Request $request, $filename)
|
||||
{
|
||||
// Get file record
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $request->user()->id)
|
||||
->where('thumbnail', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check user permission
|
||||
if ( ! $request->user()->tokenCan('master') ) {
|
||||
$this->check_file_access($request, $file);
|
||||
}
|
||||
|
||||
return $this->thumbnail_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public image thumbnail
|
||||
*
|
||||
* @param $filename
|
||||
* @param $token
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_thumbnail_public($filename, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if thumbnail is protected
|
||||
if ($shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('thumbnail', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check file access
|
||||
$this->check_file_access($shared, $file);
|
||||
|
||||
return $this->thumbnail_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check user file access
|
||||
*
|
||||
* @param $shared
|
||||
* @param $file
|
||||
*/
|
||||
protected function check_file_access($shared, $file): void
|
||||
{
|
||||
// Check by parent folder permission
|
||||
if ($shared->type === 'folder') {
|
||||
Guardian::check_item_access($file->folder_id, $shared);
|
||||
}
|
||||
|
||||
// Check by single file permission
|
||||
if ($shared->type === 'file') {
|
||||
if ($shared->item_id !== $file->unique_id) abort(403);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call and download file
|
||||
*
|
||||
* @param $file
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
private function download_file($file)
|
||||
{
|
||||
// Format pretty filename
|
||||
$file_pretty_name = $file->name . '.' . $file->mimetype;
|
||||
|
||||
// Get file path
|
||||
$path = storage_path() . '/app/file-manager/' . $file->basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!File::exists($path)) abort(404);
|
||||
|
||||
$file = File::get($path);
|
||||
$type = File::mimeType($path);
|
||||
$size = File::size($path);
|
||||
|
||||
// Create response
|
||||
$response = Response::make($file, 200);
|
||||
$response->header("Content-Type", $type);
|
||||
$response->header("Content-Disposition", 'attachment; filename=' . $file_pretty_name);
|
||||
$response->header("Content-Length", $size);
|
||||
$response->header("Accept-Ranges", "bytes");
|
||||
$response->header("Content-Range", "bytes 0-" . $size . "/" . $size);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
private function thumbnail_file($file)
|
||||
{
|
||||
// Get file path
|
||||
$path = storage_path() . '/app/file-manager/' . $file->getOriginal('thumbnail');
|
||||
|
||||
// Check if file exist
|
||||
if (!File::exists($path)) abort(404);
|
||||
|
||||
$file = File::get($path);
|
||||
$type = File::mimeType($path);
|
||||
|
||||
// Create response
|
||||
$response = Response::make($file, 200);
|
||||
$response->header("Content-Type", $type);
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
191
app/Http/Controllers/FileBrowser/BrowseController.php
Normal file
191
app/Http/Controllers/FileBrowser/BrowseController.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileBrowser;
|
||||
|
||||
use App\Http\Requests\FileBrowser\SearchRequest;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Http\Request;
|
||||
use App\FileManagerFolder;
|
||||
use App\FileManagerFile;
|
||||
use App\Share;
|
||||
|
||||
class BrowseController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Get trashed files
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function trash()
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get folders and files
|
||||
$folders_trashed = FileManagerFolder::onlyTrashed()
|
||||
->with(['trashed_folders'])
|
||||
->where('user_id', $user_id)
|
||||
->get(['parent_id', 'unique_id', 'name']);
|
||||
|
||||
$folders = FileManagerFolder::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', filter_folders_ids($folders_trashed))
|
||||
->get();
|
||||
|
||||
// Get files trashed
|
||||
$files_trashed = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->whereNotIn('folder_id', array_values(array_unique(recursiveFind($folders_trashed->toArray(), 'unique_id'))))
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files_trashed])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user shared items
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function shared()
|
||||
{
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get shared folders and files
|
||||
$folder_ids = Share::where('user_id', $user_id)
|
||||
->where('type', 'folder')
|
||||
->pluck('item_id');
|
||||
|
||||
$file_ids = Share::where('user_id', $user_id)
|
||||
->where('type', '!=', 'folder')
|
||||
->pluck('item_id');
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', $folder_ids)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', $file_ids)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get directory with files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $unique_id
|
||||
* @return Collection
|
||||
*/
|
||||
public function folder(Request $request, $unique_id)
|
||||
{
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get folder trash items
|
||||
if ($request->query('trash')) {
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->with('parent')
|
||||
->where('parent_id', $unique_id)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->with('parent')
|
||||
->where('folder_id', $unique_id)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->where('parent_id', $unique_id)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->where('folder_id', $unique_id)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user folder tree
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function navigation_tree() {
|
||||
|
||||
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('parent_id', 0)
|
||||
->where('user_id', Auth::id())
|
||||
->get(['id', 'parent_id', 'unique_id', 'name']);
|
||||
|
||||
return [
|
||||
[
|
||||
'unique_id' => 0,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'base',
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search files
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function search(SearchRequest $request)
|
||||
{
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $user_id)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$searched_folders, $searched_files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file record
|
||||
*
|
||||
* @param $unique_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function file_detail($unique_id)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
return FileManagerFile::with(['shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->firstOrFail();
|
||||
}
|
||||
}
|
||||
390
app/Http/Controllers/FileFunctions/EditItemsController.php
Normal file
390
app/Http/Controllers/FileFunctions/EditItemsController.php
Normal file
@@ -0,0 +1,390 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\Http\Requests\FileFunctions\CreateFolderRequest;
|
||||
use App\Http\Requests\FileFunctions\DeleteItemRequest;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
use App\Http\Requests\FileFunctions\MoveItemRequest;
|
||||
use App\Http\Requests\FileFunctions\UploadRequest;
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Tools\Guardian;
|
||||
use App\Http\Tools\Editor;
|
||||
use App\FileManagerFile;
|
||||
use Exception;
|
||||
|
||||
|
||||
class EditItemsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create new folder for authenticated master|editor user
|
||||
*
|
||||
* @param CreateFolderRequest $request
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_create_folder(CreateFolderRequest $request)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::create_folder($request);
|
||||
}
|
||||
|
||||
// Check permission to create folder for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
}
|
||||
|
||||
// Create new folder
|
||||
return Editor::create_folder($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new folder for guest user with edit permission
|
||||
*
|
||||
* @param CreateFolderRequest $request
|
||||
* @param $token
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_create_folder(CreateFolderRequest $request, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::create_folder($request);
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
|
||||
// Create folder
|
||||
return Editor::create_folder($request, $shared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item for authenticated master|editor user
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_rename_item(RenameItemRequest $request, $unique_id)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::rename_item($request, $unique_id);
|
||||
}
|
||||
|
||||
// Check permission to rename item for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, Auth::id());
|
||||
|
||||
// Check access to requested directory
|
||||
if ($request->type === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
}
|
||||
|
||||
// Rename Item
|
||||
return Editor::rename_item($request, $unique_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item for guest user with edit permission
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param $token
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_rename_item(RenameItemRequest $request, $unique_id, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::rename_item($request, $unique_id);
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, $shared->user_id);
|
||||
|
||||
// Check access to requested item
|
||||
if ($request->type === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
|
||||
// Rename item
|
||||
$item = Editor::rename_item($request, $unique_id, $shared);
|
||||
|
||||
// Set public url
|
||||
if ($item->type !== 'folder') {
|
||||
$item->setPublicUrl($token);
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete item for authenticated master|editor user
|
||||
*
|
||||
* @param DeleteItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_delete_item(DeleteItemRequest $request, $unique_id)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check permission to delete item for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// Prevent force delete for non-master users
|
||||
if ($request->force_delete) abort('401');
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, Auth::id());
|
||||
|
||||
// Check access to requested directory
|
||||
if ($request->type === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete item
|
||||
Editor::delete_item($request, $unique_id);
|
||||
|
||||
// Return response
|
||||
return response(null, 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete item for guest user with edit permission
|
||||
*
|
||||
* @param DeleteItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param $token
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_delete_item(DeleteItemRequest $request, $unique_id, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, $shared->user_id);
|
||||
|
||||
// Check access to requested item
|
||||
if ($request->type === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
|
||||
// Delete item
|
||||
Editor::delete_item($request, $unique_id, $shared);
|
||||
|
||||
// Return response
|
||||
return response(null, 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file for authenticated master|editor user
|
||||
*
|
||||
* @param UploadRequest $request
|
||||
* @return FileManagerFile|Model
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_upload(UploadRequest $request)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::upload($request);
|
||||
}
|
||||
|
||||
// Check if user can upload
|
||||
if (config('vuefilemanager.limit_storage_by_capacity') && user_storage_percentage() >= 100) {
|
||||
abort(423, 'You exceed your storage limit!');
|
||||
}
|
||||
|
||||
// Check permission to upload for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
}
|
||||
|
||||
// Return new uploaded file
|
||||
return Editor::upload($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file for guest user with edit permission
|
||||
*
|
||||
* @param UploadRequest $request
|
||||
* @param $token
|
||||
* @return FileManagerFile|Model
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_upload(UploadRequest $request, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::upload($request);
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
|
||||
// Return new uploaded file
|
||||
$new_file = Editor::upload($request, $shared);
|
||||
|
||||
// Set public access url
|
||||
$new_file->setPublicUrl($token);
|
||||
|
||||
return $new_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move item for authenticated master|editor user
|
||||
*
|
||||
* @param MoveItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function user_move(MoveItemRequest $request, $unique_id)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check permission to upload for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->to_unique_id, $shared);
|
||||
}
|
||||
|
||||
// Move item
|
||||
Editor::move($request, $unique_id);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move item for guest user with edit permission
|
||||
*
|
||||
* @param MoveItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param $token
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function guest_move(MoveItemRequest $request, $unique_id, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
$moving_unique_id = $unique_id;
|
||||
|
||||
if ($request->from_type !== 'folder') {
|
||||
$file = FileManagerFile::where('unique_id', $unique_id)
|
||||
->where('user_id', $shared->user_id)
|
||||
->firstOrFail();
|
||||
|
||||
$moving_unique_id = $file->folder_id;
|
||||
}
|
||||
|
||||
// Check access to requested item
|
||||
Guardian::check_item_access([
|
||||
$request->to_unique_id, $moving_unique_id
|
||||
], $shared);
|
||||
|
||||
// Move item
|
||||
Editor::move($request, $unique_id, $shared);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
69
app/Http/Controllers/FileFunctions/FavouriteController.php
Normal file
69
app/Http/Controllers/FileFunctions/FavouriteController.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class FavouriteController extends Controller
|
||||
{
|
||||
/**
|
||||
* Add folder to user favourites
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'unique_id' => 'required|integer',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user & folder
|
||||
$user = Auth::user();
|
||||
$folder = FileManagerFolder::where('unique_id', $request->unique_id)->first();
|
||||
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::favourites($user);
|
||||
}
|
||||
|
||||
// Check ownership
|
||||
if ($folder->user_id !== $user->id) abort(403);
|
||||
|
||||
// Add folder to user favourites
|
||||
$user->favourites()->syncWithoutDetaching($request->unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove folder from user favourites
|
||||
*
|
||||
* @param $unique_id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($unique_id)
|
||||
{
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::favourites($user);
|
||||
}
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourites()->detach($unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
}
|
||||
}
|
||||
107
app/Http/Controllers/FileFunctions/ShareController.php
Normal file
107
app/Http/Controllers/FileFunctions/ShareController.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\Http\Requests\Share\CreateShareRequest;
|
||||
use App\Http\Requests\Share\UpdateShareRequest;
|
||||
use App\Http\Resources\ShareResource;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Share;
|
||||
|
||||
class ShareController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get shared record
|
||||
*
|
||||
* @return ShareResource
|
||||
*/
|
||||
public function show($token)
|
||||
{
|
||||
// Get record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)
|
||||
->firstOrFail();
|
||||
|
||||
return new ShareResource($shared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate file share link
|
||||
*
|
||||
* @param CreateShareRequest $request
|
||||
* @return ShareResource
|
||||
*/
|
||||
public function store(CreateShareRequest $request)
|
||||
{
|
||||
do {
|
||||
// Generate unique token
|
||||
$token = Str::random(16);
|
||||
|
||||
} while (Share::where(DB::raw('BINARY `token`'), $token)->exists());
|
||||
|
||||
// Create shared options
|
||||
$options = [
|
||||
'password' => $request->has('password') ? Hash::make($request->password) : null,
|
||||
'type' => $request->type === 'folder' ? 'folder' : 'file',
|
||||
'protected' => $request->isPassword,
|
||||
'permission' => $request->permission,
|
||||
'item_id' => $request->unique_id,
|
||||
'user_id' => Auth::id(),
|
||||
'token' => $token,
|
||||
];
|
||||
|
||||
// Return created shared record
|
||||
return new ShareResource(Share::create($options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sharing
|
||||
*
|
||||
* @param UpdateShareRequest $request
|
||||
* @param $token
|
||||
* @return ShareResource
|
||||
*/
|
||||
public function update(UpdateShareRequest $request, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $token)
|
||||
->where('user_id', Auth::id())
|
||||
->firstOrFail();
|
||||
|
||||
// Update sharing record
|
||||
$shared->update([
|
||||
'permission' => $request->permission,
|
||||
'protected' => $request->protected,
|
||||
'password' => $request->password ? Hash::make($request->password) : $shared->password,
|
||||
]);
|
||||
|
||||
// Return shared record
|
||||
return new ShareResource($shared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete sharing item
|
||||
*
|
||||
* @param $token
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function destroy($token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $token)
|
||||
->where('user_id', Auth::id())
|
||||
->firstOrFail();
|
||||
|
||||
// Delete shared record
|
||||
$shared->delete();
|
||||
|
||||
// Done
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
115
app/Http/Controllers/FileFunctions/TrashController.php
Normal file
115
app/Http/Controllers/FileFunctions/TrashController.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use App\FileManagerFolder;
|
||||
use App\FileManagerFile;
|
||||
|
||||
class TrashController extends Controller
|
||||
{
|
||||
/**
|
||||
* Empty user trash
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
if (is_demo($user_id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get files and folders
|
||||
$folders = FileManagerFolder::onlyTrashed()->where('user_id', $user_id)->get();
|
||||
$files = FileManagerFile::onlyTrashed()->where('user_id', $user_id)->get();
|
||||
|
||||
// Force delete folder
|
||||
$folders->each->forceDelete();
|
||||
|
||||
// Force delete files
|
||||
foreach ($files as $file) {
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->thumbnail) Storage::disk('local')->delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
// Return response
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore item from trash
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $unique_id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function restore(Request $request, $unique_id)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'type' => 'required|string',
|
||||
'to_home' => 'boolean',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
if (is_demo($user_id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get folder
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
// Get folder
|
||||
$item = FileManagerFolder::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Restore item to home directory
|
||||
if ($request->has('to_home') && $request->to_home) {
|
||||
$item->parent_id = 0;
|
||||
$item->save();
|
||||
}
|
||||
} else {
|
||||
|
||||
// Get item
|
||||
$item = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Restore item to home directory
|
||||
if ($request->has('to_home') && $request->to_home) {
|
||||
$item->folder_id = 0;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Restore Item
|
||||
$item->restore();
|
||||
|
||||
// Return response
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,620 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use App\FileManagerFolder;
|
||||
use App\FileManagerFile;
|
||||
use Response;
|
||||
|
||||
|
||||
class FileManagerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get trashed files
|
||||
*
|
||||
* @param Request $request
|
||||
* @return FileManagerFile[]|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection
|
||||
*/
|
||||
public function trash()
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get folders and files
|
||||
$folders_trashed = FileManagerFolder::onlyTrashed()
|
||||
->with(['trashed_folders'])
|
||||
->where('user_id', $user_id)
|
||||
->get(['parent_id', 'unique_id', 'name']);
|
||||
|
||||
$folders = FileManagerFolder::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', filter_folders_ids($folders_trashed))
|
||||
->get();
|
||||
|
||||
// Get files trashed
|
||||
$files_trashed = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->whereNotIn('folder_id', array_values(array_unique(recursiveFind($folders_trashed->toArray(), 'unique_id'))))
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files_trashed])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get directory with files
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function folder(Request $request, $unique_id)
|
||||
{
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get folder trash items
|
||||
if ($request->query('trash')) {
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->with('parent')
|
||||
->where('parent_id', $unique_id)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->with('parent')
|
||||
->where('folder_id', $unique_id)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::with('parent')
|
||||
->where('user_id', $user_id)
|
||||
->where('parent_id', $unique_id)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::with('parent')
|
||||
->where('user_id', $user_id)
|
||||
->where('folder_id', $unique_id)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search files
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function search(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'query' => 'required|string',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))->where('user_id', $user_id)->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))->where('user_id', $user_id)->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$searched_folders, $searched_files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new folder
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function create_folder(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'parent_id' => 'required|integer',
|
||||
'name' => 'string',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get parent_id from request
|
||||
$parent_id = $request->parent_id === 0 ? 0 : $request->parent_id;
|
||||
|
||||
// Create folder
|
||||
$folder = FileManagerFolder::create([
|
||||
'user_id' => Auth::id(),
|
||||
'parent_id' => $parent_id,
|
||||
'name' => $request->has('name') ? $request->input('name') : 'New Folder',
|
||||
'type' => 'folder',
|
||||
'unique_id' => $this->get_unique_id(),
|
||||
]);
|
||||
|
||||
// Return new folder
|
||||
return $folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item name
|
||||
*
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function rename_item(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'unique_id' => 'required|integer',
|
||||
'name' => 'required|string',
|
||||
'type' => 'required|string',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Update folder name
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
$item = FileManagerFolder::where('unique_id', $request->unique_id)
|
||||
->where('user_id', $user_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->name = $request->name;
|
||||
$item->save();
|
||||
|
||||
} else {
|
||||
|
||||
$item = FileManagerFile::where('unique_id', $request->unique_id)
|
||||
->where('user_id', $user_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->name = $request->name;
|
||||
$item->save();
|
||||
}
|
||||
|
||||
// Return updated item
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete item
|
||||
*
|
||||
* @param Request $request
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete_item(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'unique_id' => 'required|integer',
|
||||
'type' => 'required|string',
|
||||
'force_delete' => 'required|boolean',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user id
|
||||
$user = Auth::user();
|
||||
|
||||
// Delete folder
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
$item = FileManagerFolder::withTrashed()
|
||||
->with('folders')
|
||||
->where('user_id', $user->id)
|
||||
->where('unique_id', $request->unique_id)
|
||||
->first();
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourites()->detach($request->unique_id);
|
||||
|
||||
foreach ($item->files as $file) {
|
||||
|
||||
if ($request->force_delete) {
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($file->thumbnail)) Storage::disk('local')->delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
} else {
|
||||
|
||||
// Delete file from visibility
|
||||
$file->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete record
|
||||
if ($request->force_delete) {
|
||||
|
||||
$item->forceDelete();
|
||||
} else {
|
||||
|
||||
$item->delete();
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->type === 'file' || $request->type === 'image') {
|
||||
|
||||
$item = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user->id)
|
||||
->where('unique_id', $request->unique_id)
|
||||
->first();
|
||||
|
||||
if ($request->force_delete) {
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('/file-manager/' . $item->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($item->thumbnail)) Storage::disk('local')->delete('/file-manager/' . $item->thumbnail);
|
||||
|
||||
// Delete file permanently
|
||||
$item->forceDelete();
|
||||
} else {
|
||||
|
||||
// Delete file from visibility
|
||||
$item->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty user trash
|
||||
*
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function empty_trash()
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get files and folders
|
||||
$folders = FileManagerFolder::onlyTrashed()->where('user_id', $user_id)->get();
|
||||
$files = FileManagerFile::onlyTrashed()->where('user_id', $user_id)->get();
|
||||
|
||||
// Force delete every item
|
||||
$folders->each->forceDelete();
|
||||
$files->each->forceDelete();
|
||||
|
||||
// Return response
|
||||
return response('Done!', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore item from trash
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function restore_item(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'unique_id' => 'required|integer',
|
||||
'type' => 'required|string',
|
||||
'to_home' => 'boolean',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get folder
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
// Get folder
|
||||
$item = FileManagerFolder::onlyTrashed()->where('user_id', $user_id)->where('unique_id', $request->unique_id)->first();
|
||||
|
||||
// Restore item to home directory
|
||||
if ($request->has('to_home') && $request->to_home) {
|
||||
$item->parent_id = 0;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Get file
|
||||
if ($request->type === 'file' || $request->type === 'image') {
|
||||
|
||||
// Get item
|
||||
$item = FileManagerFile::onlyTrashed()->where('user_id', $user_id)->where('unique_id', $request->unique_id)->first();
|
||||
|
||||
// Restore item to home directory
|
||||
if ($request->has('to_home') && $request->to_home) {
|
||||
$item->folder_id = 0;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Restore Item
|
||||
$item->restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Item
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function delete_items(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'items' => 'required|json',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
foreach ($request->input('items') as $file) {
|
||||
|
||||
if ($file['type'] === 'file' || $file['type'] === 'image') {
|
||||
|
||||
$item = FileManagerFile::where('unique_id', $file['unique_id'])->first();
|
||||
|
||||
} else {
|
||||
|
||||
$item = FileManagerFolder::where('unique_id', $file['unique_id'])->first();
|
||||
}
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('/file-manager/' . $item->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($item->thumbnail)) {
|
||||
Storage::disk('local')->delete('/file-manager/' . $item->thumbnail);
|
||||
}
|
||||
|
||||
// Permanently delete file
|
||||
$item->forceDelete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload items
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function upload_item(Request $request)
|
||||
{
|
||||
// Check if user can upload
|
||||
if (config('vuefilemanager.limit_storage_by_capacity') && user_storage_percentage() >= 100)
|
||||
abort(423, 'You exceed your storage limit!');
|
||||
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'parent_id' => 'required|integer',
|
||||
'file' => 'required|file',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get parent_id from request
|
||||
$folder_id = $request->parent_id === 0 ? 0 : $request->parent_id;
|
||||
$file = $request->file('file');
|
||||
|
||||
// File
|
||||
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
|
||||
$filetype = 'file';
|
||||
$thumbnail = null;
|
||||
$filesize = $file->getSize();
|
||||
$directory = 'file-manager';
|
||||
|
||||
// create directory if not exist
|
||||
if (!Storage::disk('local')->exists($directory)) {
|
||||
Storage::disk('local')->makeDirectory($directory);
|
||||
}
|
||||
|
||||
// Store to disk
|
||||
Storage::disk('local')->putFileAs($directory, $file, $filename, 'public');
|
||||
|
||||
// Create image thumbnail
|
||||
if (substr($file->getMimeType(), 0, 5) == 'image') {
|
||||
|
||||
$filetype = 'image';
|
||||
$thumbnail = 'thumbnail-' . $filename;
|
||||
|
||||
// Create intervention image
|
||||
$image = Image::make($file->getRealPath());
|
||||
|
||||
$image->resize(256, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
})->save(null, 90);
|
||||
|
||||
// Store thumbnail to s3
|
||||
Storage::disk('local')->put($directory . '/' . $thumbnail, $image);
|
||||
}
|
||||
|
||||
// Store file
|
||||
$new_file = FileManagerFile::create([
|
||||
'user_id' => Auth::id(),
|
||||
'name' => pathinfo($file->getClientOriginalName())['filename'],
|
||||
'basename' => $filename,
|
||||
'folder_id' => $folder_id,
|
||||
'mimetype' => $file->getClientOriginalExtension(),
|
||||
'filesize' => $filesize,
|
||||
'type' => $filetype,
|
||||
'thumbnail' => $thumbnail,
|
||||
'unique_id' => $this->get_unique_id(),
|
||||
]);
|
||||
|
||||
return $new_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move item
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function move_item(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'from_unique_id' => 'required|integer',
|
||||
'to_unique_id' => 'required|integer',
|
||||
'from_type' => 'required|string',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
if ($request->from_type === 'folder') {
|
||||
|
||||
// Move folder
|
||||
$item = FileManagerFolder::where('user_id', $user_id)
|
||||
->where('unique_id', $request->from_unique_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->parent_id = $request->to_unique_id;
|
||||
|
||||
} else {
|
||||
|
||||
// Move file under new folder
|
||||
$item = FileManagerFile::where('user_id', $user_id)
|
||||
->where('unique_id', $request->from_unique_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->folder_id = $request->to_unique_id;
|
||||
}
|
||||
|
||||
$item->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file record
|
||||
*
|
||||
* @param $unique_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_file_detail($unique_id)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
return FileManagerFile::where('user_id', $user_id)->where('unique_id', $unique_id)->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file
|
||||
*
|
||||
* @param $filename
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_file($filename)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('basename', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Get file path
|
||||
$path = storage_path() . '/app/file-manager/' . $file->basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!File::exists($path)) abort(404);
|
||||
|
||||
$file = File::get($path);
|
||||
$type = File::mimeType($path);
|
||||
$size = File::size($path);
|
||||
|
||||
// Create response
|
||||
$response = Response::make($file, 200);
|
||||
$response->header("Content-Type", $type);
|
||||
$response->header("Content-Disposition", 'attachment; filename=' . $filename);
|
||||
$response->header("Content-Length", $size);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image thumbnail
|
||||
*
|
||||
* @param $filename
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_thumbnail($filename)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('thumbnail', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Get file path
|
||||
$path = storage_path() . '/app/file-manager/' . $file->getOriginal('thumbnail');
|
||||
|
||||
// Check if file exist
|
||||
if (!File::exists($path)) abort(404);
|
||||
|
||||
$file = File::get($path);
|
||||
$type = File::mimeType($path);
|
||||
|
||||
// Create response
|
||||
$response = Response::make($file, 200);
|
||||
$response->header("Content-Type", $type);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_unique_id(): int
|
||||
{
|
||||
// Get files and folders
|
||||
$folders = FileManagerFolder::withTrashed()->get();
|
||||
$files = FileManagerFile::withTrashed()->get();
|
||||
|
||||
// Get last ids
|
||||
$folders_unique = $folders->isEmpty() ? 0 : $folders->last()->unique_id;
|
||||
$files_unique = $files->isEmpty() ? 0 : $files->last()->unique_id;
|
||||
|
||||
// Count new unique id
|
||||
$unique_id = $folders_unique > $files_unique ? $folders_unique + 1 : $files_unique + 1;
|
||||
|
||||
return $unique_id;
|
||||
}
|
||||
}
|
||||
362
app/Http/Controllers/Sharing/FileSharingController.php
Normal file
362
app/Http/Controllers/Sharing/FileSharingController.php
Normal file
@@ -0,0 +1,362 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Sharing;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Share\AuthenticateShareRequest;
|
||||
use App\Http\Resources\ShareResource;
|
||||
use App\Http\Tools\Guardian;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\FileManagerFolder;
|
||||
use App\FileManagerFile;
|
||||
use App\User;
|
||||
use App\Share;
|
||||
|
||||
class FileSharingController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Show page index and delete access_token & shared_token cookie
|
||||
*
|
||||
* @return Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function index($token)
|
||||
{
|
||||
// Get shared token
|
||||
$shared = Share::where(\DB::raw('BINARY `token`'), $token)
|
||||
->first();
|
||||
|
||||
if (!$shared) {
|
||||
return view("index");
|
||||
}
|
||||
|
||||
// Delete old access_token if exist
|
||||
Cookie::queue('shared_access_token', '', -1);
|
||||
|
||||
// Set cookies
|
||||
if ($shared->protected) {
|
||||
|
||||
// Set shared token
|
||||
Cookie::queue('shared_token', $token, 43200);
|
||||
}
|
||||
|
||||
// Return page index
|
||||
return view("index");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Password for protected item
|
||||
*
|
||||
* @param AuthenticateShareRequest $request
|
||||
* @param $token
|
||||
* @return array
|
||||
*/
|
||||
public function authenticate(AuthenticateShareRequest $request, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Check password
|
||||
if (!Hash::check($request->password, $shared->password)) {
|
||||
|
||||
abort(401, __('vuefilemanager.incorrect_password'));
|
||||
}
|
||||
|
||||
// Get owner of shared content
|
||||
$user = User::find($shared->user_id);
|
||||
|
||||
// Define scope
|
||||
$scope = !is_null($shared->permission) ? $shared->permission : 'visitor';
|
||||
|
||||
// Generate token for visitor/editor
|
||||
$access_token = $user->createToken('shared_access_token', [$scope])->accessToken;
|
||||
|
||||
// Return authorize token with shared options
|
||||
return response(new ShareResource($shared), 200)
|
||||
->cookie('shared_token', $shared->token, 43200)
|
||||
->cookie('shared_access_token', $access_token, 43200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse private folders
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $unique_id
|
||||
* @return Collection
|
||||
*/
|
||||
public function get_private_folders(Request $request, $unique_id)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail();
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($unique_id, $shared);
|
||||
|
||||
// Get files and folders
|
||||
list($folders, $files) = $this->get_items($unique_id, $shared);
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse public folders
|
||||
*
|
||||
* @param $unique_id
|
||||
* @return Collection
|
||||
*/
|
||||
public function get_public_folders($unique_id, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Abort if folder is protected
|
||||
if ($shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($unique_id, $shared);
|
||||
|
||||
// Get files and folders
|
||||
list($folders, $files) = $this->get_items($unique_id, $shared);
|
||||
|
||||
// Set thumbnail links for public files
|
||||
$files->map(function ($item) use ($token) {
|
||||
$item->setPublicUrl($token);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared public file record
|
||||
*
|
||||
* @param $token
|
||||
* @return mixed
|
||||
*/
|
||||
public function file_public($token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Abort if file is protected
|
||||
if ($shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Get file
|
||||
$file = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('unique_id', $shared->item_id)
|
||||
->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']);
|
||||
|
||||
// Set urls
|
||||
$file->setPublicUrl($token);
|
||||
|
||||
// Return record
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared private file record
|
||||
*
|
||||
* @param $token
|
||||
* @return mixed
|
||||
*/
|
||||
public function file_private(Request $request)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail();
|
||||
|
||||
// Return record
|
||||
return FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('unique_id', $shared->item_id)
|
||||
->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get navigation tree
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function get_private_navigation_tree(Request $request)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($shared->item_id, $shared);
|
||||
|
||||
// Get folders
|
||||
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('parent_id', $shared->item_id)
|
||||
->where('user_id', $shared->user_id)
|
||||
->get(['id', 'parent_id', 'unique_id', 'name']);
|
||||
|
||||
// Return folder tree
|
||||
return [
|
||||
[
|
||||
'unique_id' => $shared->item_id,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'public',
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get navigation tree
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_public_navigation_tree($token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $token)->firstOrFail();
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($shared->item_id, $shared);
|
||||
|
||||
// Get folders
|
||||
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('parent_id', $shared->item_id)
|
||||
->where('user_id', $shared->user_id)
|
||||
->get(['id', 'parent_id', 'unique_id', 'name']);
|
||||
|
||||
// Return folder tree
|
||||
return [
|
||||
[
|
||||
'unique_id' => $shared->item_id,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'public',
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search private files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $token
|
||||
* @return Collection
|
||||
*/
|
||||
public function search_private(Request $request)
|
||||
{
|
||||
// Get shared
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
|
||||
// Get all children content
|
||||
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('user_id', $shared->user_id)
|
||||
->where('parent_id', $shared->item_id)
|
||||
->get();
|
||||
|
||||
// Get accessible folders
|
||||
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
|
||||
|
||||
// Filter files to only accessible files
|
||||
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids) {
|
||||
return in_array($file->folder_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Filter folders to only accessible folders
|
||||
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
|
||||
return in_array($folder->unique_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search public files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $token
|
||||
* @return Collection
|
||||
*/
|
||||
public function search_public(Request $request, $token)
|
||||
{
|
||||
// Get shared
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if folder is protected
|
||||
if ($shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
|
||||
// Get all children content
|
||||
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('user_id', $shared->user_id)
|
||||
->where('parent_id', $shared->item_id)
|
||||
->get();
|
||||
|
||||
// Get accessible folders
|
||||
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
|
||||
|
||||
// Filter files
|
||||
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids, $token) {
|
||||
|
||||
// Set public urls
|
||||
$file->setPublicUrl($token);
|
||||
|
||||
// check if item is in accessible folders
|
||||
return in_array($file->folder_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Filter folders
|
||||
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
|
||||
|
||||
// check if item is in accessible folders
|
||||
return in_array($folder->unique_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get folders and files
|
||||
*
|
||||
* @param $unique_id
|
||||
* @param $shared
|
||||
* @return array
|
||||
*/
|
||||
private function get_items($unique_id, $shared): array
|
||||
{
|
||||
$folders = FileManagerFolder::where('user_id', $shared->user_id)
|
||||
->where('parent_id', $unique_id)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('folder_id', $unique_id)
|
||||
->get();
|
||||
|
||||
return [$folders, $files];
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\User;
|
||||
use ByteUnits\Metric;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Http\Request;
|
||||
use ByteUnits\Metric;
|
||||
use App\User;
|
||||
|
||||
|
||||
class UserAccountController extends Controller
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get all user data to frontend
|
||||
*
|
||||
* @return array|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
|
||||
* @return array
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get User
|
||||
$user = User::with(['favourites', 'latest_uploads'])->where('id', $user_id)->first();
|
||||
$user = User::with(['favourites', 'latest_uploads'])
|
||||
->where('id', Auth::id())
|
||||
->first();
|
||||
|
||||
return [
|
||||
'user' => $user->only(['name', 'email', 'avatar']),
|
||||
'favourites' => $user->favourites->makeHidden(['pivot']),
|
||||
'latest_uploads' => $user->latest_uploads->makeHidden(['user_id', 'basename']),
|
||||
|
||||
'storage' => [
|
||||
'storage' => [
|
||||
'used' => Metric::bytes($user->used_capacity)->format(),
|
||||
'capacity' => format_gigabytes(config('vuefilemanager.user_storage_capacity')),
|
||||
'percentage' => get_storage_fill_percentage($user->used_capacity, config('vuefilemanager.user_storage_capacity')),
|
||||
@@ -43,14 +42,13 @@ class UserAccountController extends Controller
|
||||
* Update user profile
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update_profile(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'avatar' => 'file',
|
||||
'_method' => 'string',
|
||||
'name' => 'string',
|
||||
'value' => 'string',
|
||||
]);
|
||||
@@ -61,6 +59,10 @@ class UserAccountController extends Controller
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
if ($request->hasFile('avatar')) {
|
||||
|
||||
// Update avatar
|
||||
@@ -75,14 +77,14 @@ class UserAccountController extends Controller
|
||||
$user->update(make_single_input($request));
|
||||
}
|
||||
|
||||
return response('Saved!', 200);
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change user password
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function change_password(Request $request)
|
||||
{
|
||||
@@ -94,60 +96,14 @@ class UserAccountController extends Controller
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Change and store new password
|
||||
$user->password = Hash::make($request->input('password'));
|
||||
$user->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add folder to user favourites
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function add_to_favourites(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'unique_id' => 'required|integer',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Add folder to user favourites
|
||||
$user->favourites()->attach($request->unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove folder from user favourites
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function remove_from_favourites(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'unique_id' => 'required|integer',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourites()->detach($request->unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
return response('Changed!', 204);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Http;
|
||||
|
||||
use App\Http\Middleware\CookieAuth;
|
||||
use App\Http\Middleware\LastCheck;
|
||||
use App\Http\Middleware\SharedAuth;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
@@ -40,6 +42,7 @@ class Kernel extends HttpKernel
|
||||
],
|
||||
|
||||
'api' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
//'throttle:60,1',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
@@ -53,6 +56,8 @@ class Kernel extends HttpKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
'auth.master' => CookieAuth::class,
|
||||
'auth.shared' => SharedAuth::class,
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
@@ -63,7 +68,8 @@ class Kernel extends HttpKernel
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'auth.cookie' => CookieAuth::class,
|
||||
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
|
||||
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -77,6 +83,7 @@ class Kernel extends HttpKernel
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
CookieAuth::class,
|
||||
SharedAuth::class,
|
||||
\App\Http\Middleware\Authenticate::class,
|
||||
\Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class CookieAuth
|
||||
{
|
||||
@@ -16,14 +17,12 @@ class CookieAuth
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$request->bearerToken()) {
|
||||
if ($request->hasCookie('token')) {
|
||||
if ($request->hasCookie('access_token')) {
|
||||
|
||||
$token = $request->cookie('token');
|
||||
$access_token = $request->cookie('access_token');
|
||||
|
||||
$request->headers->add(['Authorization' => 'Bearer ' . $token]);
|
||||
$request->headers->add(['Authorization' => 'Bearer ' . $access_token]);
|
||||
|
||||
} else {
|
||||
abort(401);
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
|
||||
29
app/Http/Middleware/SharedAuth.php
Normal file
29
app/Http/Middleware/SharedAuth.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class SharedAuth
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$request->bearerToken()) {
|
||||
if ($request->hasCookie('shared_access_token')) {
|
||||
|
||||
$shared_access_token = $request->cookie('shared_access_token');
|
||||
|
||||
$request->headers->add(['Authorization' => 'Bearer ' . $shared_access_token]);
|
||||
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
30
app/Http/Requests/Auth/CheckAccountRequest.php
Normal file
30
app/Http/Requests/Auth/CheckAccountRequest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Auth;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CheckAccountRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|string|email',
|
||||
];
|
||||
}
|
||||
}
|
||||
30
app/Http/Requests/FileBrowser/SearchRequest.php
Normal file
30
app/Http/Requests/FileBrowser/SearchRequest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\FileBrowser;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class SearchRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'query' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
32
app/Http/Requests/FileFunctions/CreateFolderRequest.php
Normal file
32
app/Http/Requests/FileFunctions/CreateFolderRequest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\FileFunctions;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class CreateFolderRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'parent_id' => 'required|integer',
|
||||
'name' => 'string',
|
||||
];
|
||||
}
|
||||
}
|
||||
32
app/Http/Requests/FileFunctions/DeleteItemRequest.php
Normal file
32
app/Http/Requests/FileFunctions/DeleteItemRequest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\FileFunctions;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DeleteItemRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'type' => 'required|string',
|
||||
'force_delete' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
32
app/Http/Requests/FileFunctions/MoveItemRequest.php
Normal file
32
app/Http/Requests/FileFunctions/MoveItemRequest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\FileFunctions;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class MoveItemRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'to_unique_id' => 'required|integer',
|
||||
'from_type' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
32
app/Http/Requests/FileFunctions/RenameItemRequest.php
Normal file
32
app/Http/Requests/FileFunctions/RenameItemRequest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\FileFunctions;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class RenameItemRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string',
|
||||
'type' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
32
app/Http/Requests/FileFunctions/UploadRequest.php
Normal file
32
app/Http/Requests/FileFunctions/UploadRequest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\FileFunctions;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class UploadRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'parent_id' => 'required|integer',
|
||||
'file' => 'required|file',
|
||||
];
|
||||
}
|
||||
}
|
||||
20
app/Http/Requests/Share/AuthenticateShareRequest.php
Normal file
20
app/Http/Requests/Share/AuthenticateShareRequest.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Share;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class AuthenticateShareRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'password' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
35
app/Http/Requests/Share/CreateShareRequest.php
Normal file
35
app/Http/Requests/Share/CreateShareRequest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Share;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class CreateShareRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return Auth::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'isPassword' => 'required|boolean',
|
||||
'unique_id' => 'required|integer',
|
||||
'type' => 'required|string',
|
||||
'permission' => 'string',
|
||||
'password' => 'string',
|
||||
];
|
||||
}
|
||||
}
|
||||
33
app/Http/Requests/Share/UpdateShareRequest.php
Normal file
33
app/Http/Requests/Share/UpdateShareRequest.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Share;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class UpdateShareRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return Auth::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'protected' => 'required|boolean',
|
||||
'permission' => 'nullable|string',
|
||||
'password' => 'string',
|
||||
];
|
||||
}
|
||||
}
|
||||
34
app/Http/Resources/ShareResource.php
Normal file
34
app/Http/Resources/ShareResource.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class ShareResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'shares',
|
||||
'attributes' => [
|
||||
'permission' => $this->permission,
|
||||
'protected' => $this->protected,
|
||||
'item_id' => $this->item_id,
|
||||
'token' => $this->token,
|
||||
'link' => $this->link,
|
||||
'type' => $this->type,
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
143
app/Http/Tools/Demo.php
Normal file
143
app/Http/Tools/Demo.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Tools;
|
||||
|
||||
use App;
|
||||
use App\Share;
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
use App\User;
|
||||
use ByteUnits\Metric;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
|
||||
|
||||
class Demo
|
||||
{
|
||||
/**
|
||||
* Create new directory
|
||||
*
|
||||
* @param $request
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function create_folder($request)
|
||||
{
|
||||
// Get variables
|
||||
$user_scope = $request->user() ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$name = $request->has('name') ? $request->input('name') : 'New Folder';
|
||||
|
||||
return [
|
||||
'user_id' => 1,
|
||||
'id' => random_int(1000, 9999),
|
||||
'parent_id' => random_int(1000, 9999),
|
||||
'name' => $name,
|
||||
'type' => 'folder',
|
||||
'unique_id' => random_int(1000, 9999),
|
||||
'user_scope' => $user_scope,
|
||||
'items' => '0',
|
||||
'updated_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
'created_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item name
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return mixed
|
||||
*/
|
||||
public static function rename_item($request, $unique_id)
|
||||
{
|
||||
// Get item
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
$item = FileManagerFolder::where('unique_id', $unique_id)
|
||||
->where('user_id', 1)
|
||||
->first();
|
||||
|
||||
} else {
|
||||
|
||||
$item = FileManagerFile::where('unique_id', $unique_id)
|
||||
->where('user_id', 1)
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($item) {
|
||||
$item->name = $request->name;
|
||||
|
||||
return $item;
|
||||
|
||||
} else {
|
||||
|
||||
return [
|
||||
'unique_id' => $request->unique_id,
|
||||
'name' => $request->name,
|
||||
'type' => $request->type,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param $request
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function upload($request)
|
||||
{
|
||||
// Get user data
|
||||
$user_scope = $request->user() ? $request->user()->token()->scopes[0] : 'editor';
|
||||
|
||||
// File
|
||||
$file = $request->file('file');
|
||||
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
|
||||
$thumbnail = null;
|
||||
$filesize = $file->getSize();
|
||||
$filetype = get_file_type($file);
|
||||
|
||||
return [
|
||||
'id' => random_int(1000, 9999),
|
||||
'unique_id' => random_int(1000, 9999),
|
||||
'folder_id' => $request->parent_id,
|
||||
'thumbnail' => 'data:' . $request->file('file')->getMimeType() . ';base64, ' . base64_encode(file_get_contents($request->file('file'))),
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'basename' => $filename,
|
||||
'mimetype' => $file->getClientOriginalExtension(),
|
||||
'filesize' => Metric::bytes($filesize)->format(),
|
||||
'type' => $filetype,
|
||||
'file_url' => 'https://vuefilemanager.hi5ve.digital/assets/vue-file-manager-preview.jpg',
|
||||
'user_scope' => $user_scope,
|
||||
'created_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
'updated_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 204 status
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public static function response_204() {
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 204 status
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public static function favourites($user) {
|
||||
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
}
|
||||
}
|
||||
294
app/Http/Tools/Editor.php
Normal file
294
app/Http/Tools/Editor.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Tools;
|
||||
|
||||
use App;
|
||||
use App\Share;
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
use App\User;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
|
||||
|
||||
class Editor
|
||||
{
|
||||
/**
|
||||
* Create new directory
|
||||
*
|
||||
* @param $request
|
||||
* @param null $shared
|
||||
* @return FileManagerFolder|\Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public static function create_folder($request, $shared = null)
|
||||
{
|
||||
// Get variables
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$name = $request->has('name') ? $request->input('name') : 'New Folder';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// Create folder
|
||||
$folder = FileManagerFolder::create([
|
||||
'parent_id' => $request->parent_id,
|
||||
'unique_id' => get_unique_id(),
|
||||
'user_scope' => $user_scope,
|
||||
'user_id' => $user_id,
|
||||
'type' => 'folder',
|
||||
'name' => $name,
|
||||
]);
|
||||
|
||||
// Return new folder
|
||||
return $folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item name
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param null $shared
|
||||
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function rename_item($request, $unique_id, $shared = null)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// Get item
|
||||
$item = get_item($request->type, $unique_id, $user_id);
|
||||
|
||||
// Rename item
|
||||
$item->update([
|
||||
'name' => $request->name
|
||||
]);
|
||||
|
||||
// Return updated item
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file or folder
|
||||
*
|
||||
* @param $request
|
||||
* @param $unique_id
|
||||
* @param null $shared
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function delete_item($request, $unique_id, $shared = null)
|
||||
{
|
||||
// Get user id
|
||||
$user = is_null($shared) ? Auth::user() : User::findOrFail($shared->user_id);
|
||||
|
||||
// Delete folder
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
// Get folder
|
||||
$folder = FileManagerFolder::withTrashed()
|
||||
->with(['folders'])
|
||||
->where('user_id', $user->id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Get folder shared record
|
||||
$shared = Share::where('user_id', $user->id)
|
||||
->where('type', '=', 'folder')
|
||||
->where('item_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Delete folder shared record
|
||||
if ($shared) {
|
||||
$shared->delete();
|
||||
}
|
||||
|
||||
// Force delete children files
|
||||
if ($request->force_delete) {
|
||||
|
||||
// Get children folder ids
|
||||
$child_folders = filter_folders_ids($folder->trashed_folders, 'unique_id');
|
||||
|
||||
// Get children files
|
||||
$files = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user->id)
|
||||
->whereIn('folder_id', Arr::flatten([$unique_id, $child_folders]))
|
||||
->get();
|
||||
|
||||
// Remove all children files
|
||||
foreach ($files as $file) {
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($file->thumbnail)) Storage::disk('local')->delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
// Delete folder record
|
||||
$folder->forceDelete();
|
||||
}
|
||||
|
||||
// Soft delete items
|
||||
if (!$request->force_delete) {
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourites()->detach($unique_id);
|
||||
|
||||
// Soft delete folder record
|
||||
$folder->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete item
|
||||
if ($request->type !== 'folder') {
|
||||
|
||||
// Get file
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user->id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Get folder shared record
|
||||
$shared = Share::where('user_id', $user->id)
|
||||
->where('type', '=', 'file')
|
||||
->where('item_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Delete file shared record
|
||||
if ($shared) {
|
||||
$shared->delete();
|
||||
}
|
||||
|
||||
// Force delete file
|
||||
if ($request->force_delete) {
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->thumbnail) Storage::disk('local')->delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
// Soft delete file
|
||||
if (!$request->force_delete) {
|
||||
|
||||
// Soft delete file
|
||||
$file->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param $request
|
||||
* @param null $shared
|
||||
* @return FileManagerFile|\Illuminate\Database\Eloquent\Model
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function upload($request, $shared = null)
|
||||
{
|
||||
// Get user data
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// Get parent_id from request
|
||||
$folder_id = $request->parent_id === 0 ? 0 : $request->parent_id;
|
||||
$file = $request->file('file');
|
||||
|
||||
// File
|
||||
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
|
||||
$filetype = get_file_type($file);
|
||||
$filesize = $file->getSize();
|
||||
$directory = 'file-manager';
|
||||
$thumbnail = null;
|
||||
|
||||
// create directory if not exist
|
||||
if (!Storage::disk('local')->exists($directory)) {
|
||||
Storage::disk('local')->makeDirectory($directory);
|
||||
}
|
||||
|
||||
// Store to disk
|
||||
Storage::disk('local')->putFileAs($directory, $file, $filename, 'public');
|
||||
|
||||
// Create image thumbnail
|
||||
if ($filetype == 'image') {
|
||||
|
||||
// Get thumbnail name
|
||||
$thumbnail = 'thumbnail-' . $filename;
|
||||
|
||||
// Create intervention image
|
||||
$image = Image::make($file->getRealPath())->orientate();
|
||||
|
||||
// Resize image
|
||||
$image->resize(256, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
})->stream();
|
||||
|
||||
// Store thumbnail to disk
|
||||
Storage::disk('local')->put($directory . '/' . $thumbnail, $image);
|
||||
}
|
||||
|
||||
// Store file
|
||||
$options = [
|
||||
'name' => pathinfo($file->getClientOriginalName())['filename'],
|
||||
'mimetype' => $file->getClientOriginalExtension(),
|
||||
'unique_id' => get_unique_id(),
|
||||
'user_scope' => $user_scope,
|
||||
'folder_id' => $folder_id,
|
||||
'thumbnail' => $thumbnail,
|
||||
'basename' => $filename,
|
||||
'filesize' => $filesize,
|
||||
'type' => $filetype,
|
||||
'user_id' => $user_id,
|
||||
];
|
||||
|
||||
// Return new file
|
||||
return FileManagerFile::create($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move folder or file to new location
|
||||
*
|
||||
* @param $request
|
||||
* @param $unique_id
|
||||
* @param null $shared
|
||||
*/
|
||||
public static function move($request, $unique_id, $shared = null)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
if ($request->from_type === 'folder') {
|
||||
|
||||
// Move folder
|
||||
$item = FileManagerFolder::where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->update([
|
||||
'parent_id' => $request->to_unique_id
|
||||
]);
|
||||
|
||||
} else {
|
||||
|
||||
// Move file under new folder
|
||||
$item = FileManagerFile::where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->update([
|
||||
'folder_id' => $request->to_unique_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
app/Http/Tools/Guardian.php
Normal file
42
app/Http/Tools/Guardian.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Tools;
|
||||
|
||||
use App;
|
||||
use App\FileManagerFolder;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
|
||||
class Guardian
|
||||
{
|
||||
/**
|
||||
* Check access to requested directory
|
||||
*
|
||||
* @param integer|array $requested_id
|
||||
* @param string $shared Shared record detail
|
||||
*/
|
||||
public static function check_item_access($requested_id, $shared)
|
||||
{
|
||||
// Get all children folders
|
||||
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('user_id', $shared->user_id)
|
||||
->where('parent_id', $shared->item_id)
|
||||
->get();
|
||||
|
||||
// Get all authorized parent folders by shared folder as root of tree
|
||||
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
|
||||
|
||||
// Check user access
|
||||
if ( is_array($requested_id) ) {
|
||||
foreach ($requested_id as $id) {
|
||||
if (!in_array($id, $accessible_folder_ids))
|
||||
abort(403);
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_array($requested_id)) {
|
||||
if (! in_array($requested_id, $accessible_folder_ids))
|
||||
abort(403);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,102 @@
|
||||
<?php
|
||||
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Share;
|
||||
use ByteUnits\Metric;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
|
||||
/**
|
||||
* Get app version from config
|
||||
*
|
||||
* @return \Illuminate\Config\Repository|mixed
|
||||
*/
|
||||
function get_version() {
|
||||
return config('vuefilemanager.version');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if is demo
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function is_demo($user_id) {
|
||||
|
||||
return env('APP_DEMO', false) && $user_id === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get folder or file item
|
||||
*
|
||||
* @param $type
|
||||
* @param $unique_id
|
||||
* @param $user_id
|
||||
* @return \Illuminate\Database\Eloquent\Builder|Model
|
||||
*/
|
||||
function get_item($type, $unique_id, $user_id) {
|
||||
|
||||
if ($type === 'folder') {
|
||||
|
||||
// Return folder item
|
||||
return FileManagerFolder::where('unique_id', $unique_id)
|
||||
->where('user_id', $user_id)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
// Return file item
|
||||
return FileManagerFile::where('unique_id', $unique_id)
|
||||
->where('user_id', $user_id)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared token
|
||||
*
|
||||
* @param $token
|
||||
* @return \Illuminate\Database\Eloquent\Builder|Model
|
||||
*/
|
||||
function get_shared($token) {
|
||||
|
||||
return Share::where(DB::raw('BINARY `token`'), $token)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if shared permission is editor
|
||||
*
|
||||
* @param $shared
|
||||
* @return bool
|
||||
*/
|
||||
function is_editor($shared) {
|
||||
|
||||
return $shared->permission === 'editor';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function get_unique_id(): int
|
||||
{
|
||||
// Get files and folders
|
||||
$folders = FileManagerFolder::withTrashed()->get();
|
||||
$files = FileManagerFile::withTrashed()->get();
|
||||
|
||||
// Get last ids
|
||||
$folders_unique = $folders->isEmpty() ? 0 : $folders->last()->unique_id;
|
||||
$files_unique = $files->isEmpty() ? 0 : $files->last()->unique_id;
|
||||
|
||||
// Count new unique id
|
||||
$unique_id = $folders_unique > $files_unique ? $folders_unique + 1 : $files_unique + 1;
|
||||
|
||||
return $unique_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store user avatar to storage
|
||||
@@ -54,7 +146,6 @@ function check_directory($directory)
|
||||
*/
|
||||
function make_single_input($request)
|
||||
{
|
||||
|
||||
// Create container
|
||||
$data = [];
|
||||
|
||||
@@ -100,9 +191,9 @@ function get_storage_fill_percentage($used, $capacity)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function user_storage_percentage() {
|
||||
|
||||
$user = \Illuminate\Support\Facades\Auth::user();
|
||||
function user_storage_percentage()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
return get_storage_fill_percentage($user->used_capacity, config('vuefilemanager.user_storage_capacity'));
|
||||
}
|
||||
@@ -152,9 +243,49 @@ function appeared_once($arr)
|
||||
* @param $folders
|
||||
* @return array
|
||||
*/
|
||||
function filter_folders_ids($folders)
|
||||
function filter_folders_ids($folders, $by_column = 'unique_id')
|
||||
{
|
||||
$folder_unique_ids = recursiveFind($folders->toArray(), 'unique_id');
|
||||
$folder_unique_ids = recursiveFind($folders->toArray(), $by_column);
|
||||
|
||||
return appeared_once($folder_unique_ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format localized date
|
||||
*
|
||||
* @param $date
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
function format_date($date, $format = '%d. %B. %Y, %H:%M')
|
||||
{
|
||||
$start = Carbon::parse($date);
|
||||
|
||||
return $start->formatLocalized($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file type from mimetype
|
||||
*
|
||||
* @param $file
|
||||
* @return string
|
||||
*/
|
||||
function get_file_type($file)
|
||||
{
|
||||
// Get mimetype from file
|
||||
$mimetype = explode('/', $file->getMimeType());
|
||||
|
||||
switch ($mimetype[0]) {
|
||||
case 'image':
|
||||
return 'image';
|
||||
break;
|
||||
case 'video':
|
||||
return 'video';
|
||||
break;
|
||||
case 'audio':
|
||||
return 'audio';
|
||||
break;
|
||||
default:
|
||||
return 'file';
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class TestMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->from('peterpapp@makingcg.com')->view('welcome');
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class ResetPassword extends Notification
|
||||
$reset_url = url('/create-new-password?token=' . $this->token);
|
||||
|
||||
return (new MailMessage)
|
||||
->subject('Reset password for your account on ' . env('APP_NAME'))
|
||||
->subject('Reset password for your account on ' . config('vuefilemanager.app_name'))
|
||||
->line('You are receiving this email because we received a password reset request for your account.')
|
||||
->action('Reset Password', $reset_url)
|
||||
->line('If you did not request a password reset, no further action is required.');
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
@@ -23,6 +25,11 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
Schema::defaultStringLength(191);
|
||||
|
||||
$get_time_locale = App::getLocale() . '_' . mb_strtoupper(App::getLocale());
|
||||
|
||||
// Set locale for carbon dates
|
||||
setlocale(LC_TIME, $get_time_locale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,5 +27,17 @@ class AuthServiceProvider extends ServiceProvider
|
||||
$this->registerPolicies();
|
||||
|
||||
Passport::routes();
|
||||
|
||||
Passport::tokensCan([
|
||||
'master' => 'Master',
|
||||
'editor' => 'Editor',
|
||||
'visitor' => 'Visitor',
|
||||
]);
|
||||
|
||||
Passport::setDefaultScope([
|
||||
'master',
|
||||
'editor',
|
||||
'visitor',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
51
app/Share.php
Normal file
51
app/Share.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Share
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property string $token
|
||||
* @property int $item_id
|
||||
* @property string $type
|
||||
* @property string|null $permission
|
||||
* @property int $protected
|
||||
* @property string|null $password
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read string $link
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereItemId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share wherePassword($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share wherePermission($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereProtected($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Share extends Model
|
||||
{
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected $appends = ['link'];
|
||||
|
||||
/**
|
||||
* Generate share link
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLinkAttribute() {
|
||||
|
||||
return url('/shared', ['token' => $this->attributes['token']]);
|
||||
}
|
||||
}
|
||||
41
app/User.php
41
app/User.php
@@ -12,6 +12,47 @@ use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
|
||||
/**
|
||||
* App\User
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $email
|
||||
* @property \Illuminate\Support\Carbon|null $email_verified_at
|
||||
* @property string $password
|
||||
* @property \Illuminate\Contracts\Routing\UrlGenerator|string $avatar
|
||||
* @property string|null $remember_token
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Passport\Client[] $clients
|
||||
* @property-read int|null $clients_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $favourites
|
||||
* @property-read int|null $favourites_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $files
|
||||
* @property-read int|null $files_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $files_with_trashed
|
||||
* @property-read int|null $files_with_trashed_count
|
||||
* @property-read mixed $used_capacity
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $latest_uploads
|
||||
* @property-read int|null $latest_uploads_count
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
|
||||
* @property-read int|null $notifications_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Passport\Token[] $tokens
|
||||
* @property-read int|null $tokens_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereAvatar($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereEmail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereEmailVerifiedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User wherePassword($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRememberToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereUpdatedAt($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens, Notifiable;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.2",
|
||||
"askedio/laravel-soft-cascade": "^6.0",
|
||||
"doctrine/dbal": "^2.10",
|
||||
"fideloper/proxy": "^4.0",
|
||||
"fruitcake/laravel-cors": "^1.0",
|
||||
"gabrielelana/byte-units": "^0.5.0",
|
||||
@@ -21,6 +21,7 @@
|
||||
"teamtnt/laravel-scout-tntsearch-driver": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-ide-helper": "^2.7",
|
||||
"facade/ignition": "^1.4",
|
||||
"fzaninotto/faker": "^1.4",
|
||||
"mockery/mockery": "^1.0",
|
||||
|
||||
1608
composer.lock
generated
1608
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,14 @@
|
||||
|
||||
return [
|
||||
|
||||
'version' => '1.4.1',
|
||||
|
||||
// Your app name
|
||||
'app_name' => 'VueFileManager',
|
||||
|
||||
// Your app logo
|
||||
'app_logo' => '/assets/images/hero.svg',
|
||||
|
||||
// Enable or disable user account registration
|
||||
'registration' => true,
|
||||
|
||||
@@ -9,5 +17,5 @@ return [
|
||||
'limit_storage_by_capacity' => true,
|
||||
|
||||
// Define user storage capacity in MB. E.g. value 2000 is 2.00GB
|
||||
'user_storage_capacity' => 5000,
|
||||
'user_storage_capacity' => 300,
|
||||
];
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ChangeTypeAttributeInFileManagerFilesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
DB::statement('ALTER TABLE file_manager_files MODIFY type TEXT;');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateSharesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('shares', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->bigInteger('user_id');
|
||||
$table->string('token', 16)->unique();
|
||||
$table->bigInteger('item_id');
|
||||
$table->enum('type', ['file', 'files', 'folder']);
|
||||
$table->enum('permission', ['visitor', 'editor'])->nullable();
|
||||
$table->boolean('protected');
|
||||
$table->string('password')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('shares');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddUserScopeToFileManagerFilesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
$table->string('user_scope')->after('type')->default('master');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddUserScopeToFileManagerFoldersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('file_manager_folders', function (Blueprint $table) {
|
||||
$table->string('user_scope')->after('type')->default('master');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('file_manager_folders', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
# Host: 127.0.0.1 (MySQL 5.7.25)
|
||||
# Database: file-manager
|
||||
# Generation Time: 2020-03-14 17:32:56 +0000
|
||||
# Generation Time: 2020-04-03 07:57:39 +0000
|
||||
# ************************************************************
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ CREATE TABLE `file_manager_files` (
|
||||
`basename` text COLLATE utf8mb4_unicode_ci,
|
||||
`mimetype` text COLLATE utf8mb4_unicode_ci,
|
||||
`filesize` text COLLATE utf8mb4_unicode_ci,
|
||||
`type` enum('image','file') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`type` text COLLATE utf8mb4_unicode_ci,
|
||||
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL,
|
||||
@@ -122,7 +122,8 @@ VALUES
|
||||
(10,'2019_08_19_000000_create_failed_jobs_table',1),
|
||||
(11,'2020_03_03_065147_add_user_id_to_file_manager_files_table',2),
|
||||
(12,'2020_03_03_065155_add_user_id_to_file_manager_folders_table',2),
|
||||
(13,'2020_03_03_070319_create_favourites_folders_table',3);
|
||||
(13,'2020_03_03_070319_create_favourites_folders_table',3),
|
||||
(14,'2020_04_02_055021_change_type_attribute_in_file_manager_files_table',4);
|
||||
|
||||
/*!40000 ALTER TABLE `migrations` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
@@ -249,11 +250,11 @@ DROP TABLE IF EXISTS `users`;
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`email_verified_at` timestamp NULL DEFAULT NULL,
|
||||
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`avatar` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`password` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`avatar` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL,
|
||||
1116
package-lock.json
generated
1116
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -12,20 +12,22 @@
|
||||
"devDependencies": {
|
||||
"axios": "^0.19",
|
||||
"cross-env": "^5.1",
|
||||
"laravel-mix": "^5.0.1",
|
||||
"laravel-mix": "^5.0.4",
|
||||
"resolve-url-loader": "^2.3.1",
|
||||
"sass-loader": "^8.0.2",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.26",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
||||
"@fortawesome/vue-fontawesome": "^0.1.9",
|
||||
"css-element-queries": "^1.2.3",
|
||||
"lodash": "^4.17.15",
|
||||
"node-sass": "^4.13.1",
|
||||
"vee-validate": "^3.2.5",
|
||||
"node-sass": "^4.14.0",
|
||||
"vee-validate": "^3.3.0",
|
||||
"vue": "^2.6.10",
|
||||
"vuex": "^3.0.1"
|
||||
"vue-i18n": "^8.17.4",
|
||||
"vue-router": "^3.1.6",
|
||||
"vuex": "^3.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,13 @@
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
AddType video/ogg .ogv
|
||||
AddType video/mp4 .mp4
|
||||
AddType video/webm .webm
|
||||
<ifModule mod_headers.c>
|
||||
Header set Connection keep-alive
|
||||
</ifModule>
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
BIN
public/assets/images/app-icon.png
Normal file
BIN
public/assets/images/app-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
4
public/css/app.css
vendored
4
public/css/app.css
vendored
@@ -1 +1,3 @@
|
||||
@import url(https://fonts.googleapis.com/css?family=Nunito:400,700,900&display=swap);
|
||||
@import url(https://fonts.googleapis.com/css2?family=Nunito:wght@200;
|
||||
|
||||
300;400;600;700;900&display=swap);#application-wrapper{display:flex;height:100%}#application-wrapper #content{position:relative;width:100%}
|
||||
2
public/js/main.js
vendored
2
public/js/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -4,8 +4,14 @@
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* vue-i18n v8.17.4
|
||||
* (c) 2020 kazuya kawaguchi
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* vee-validate v3.2.5
|
||||
* vee-validate v3.3.0
|
||||
* (c) 2020 Abdelrahman Awad
|
||||
* @license MIT
|
||||
*/
|
||||
@@ -20,7 +26,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* vuex v3.1.3
|
||||
* vuex v3.3.0
|
||||
* (c) 2020 Evan You
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"/js/main.js": "/js/main.js?id=cef949b486ef02300d3b",
|
||||
"/css/app.css": "/css/app.css?id=1864eb943a745d7d07e2"
|
||||
"/js/main.js": "/js/main.js",
|
||||
"/css/app.css": "/css/app.css"
|
||||
}
|
||||
|
||||
@@ -1,25 +1,134 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<VueFileManager style="height: 100%; width: 100%"/>
|
||||
<div id="vue-file-manager" :class="appSize">
|
||||
|
||||
<!--System alerts-->
|
||||
<Alert />
|
||||
|
||||
<div id="application-wrapper" v-if="layout === 'authorized'">
|
||||
|
||||
<!--Share Item setup-->
|
||||
<ShareCreate />
|
||||
<ShareEdit />
|
||||
|
||||
<!--Move item setup-->
|
||||
<MoveItem />
|
||||
|
||||
<!--Mobile Menu-->
|
||||
<MobileMenu />
|
||||
|
||||
<!--Navigation Sidebar-->
|
||||
<Sidebar/>
|
||||
|
||||
<!--File page-->
|
||||
<router-view/>
|
||||
</div>
|
||||
|
||||
<router-view v-if="layout === 'unauthorized'"/>
|
||||
|
||||
<!--Background vignette-->
|
||||
<Vignette />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueFileManager from './components/VueFileManager.vue'
|
||||
import MobileMenu from '@/components/FilesView/MobileMenu'
|
||||
import ShareCreate from '@/components/Others/ShareCreate'
|
||||
import ShareEdit from '@/components/Others/ShareEdit'
|
||||
import MoveItem from '@/components/Others/MoveItem'
|
||||
import Vignette from '@/components/Others/Vignette'
|
||||
import Sidebar from '@/components/Sidebar/Sidebar'
|
||||
import Alert from '@/components/FilesView/Alert'
|
||||
import {ResizeSensor} from 'css-element-queries'
|
||||
import { includes } from 'lodash'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from "./bus"
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
VueFileManager
|
||||
ShareCreate,
|
||||
MobileMenu,
|
||||
ShareEdit,
|
||||
MoveItem,
|
||||
Vignette,
|
||||
Sidebar,
|
||||
Alert,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'appSize', 'isLogged', 'isGuest'
|
||||
]),
|
||||
layout() {
|
||||
if (includes(['VerifyByPassword', 'SharedPage', 'NotFoundShared', 'SignIn', 'SignUp', 'ForgottenPassword', 'CreateNewPassword'], this.$route.name)) {
|
||||
return 'unauthorized'
|
||||
}
|
||||
|
||||
return 'authorized'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAppResize() {
|
||||
let appView = document.getElementById('vue-file-manager')
|
||||
.offsetWidth
|
||||
|
||||
if (appView <= 690)
|
||||
this.$store.commit('SET_APP_WIDTH', 'small')
|
||||
if (appView > 690 && appView < 960)
|
||||
this.$store.commit('SET_APP_WIDTH', 'medium')
|
||||
if (appView > 960)
|
||||
this.$store.commit('SET_APP_WIDTH', 'large')
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
// Store config to vuex
|
||||
this.$store.commit('SET_AUTHORIZED', this.$root.$data.config.hasAuthCookie)
|
||||
this.$store.commit('SET_CONFIG', this.$root.$data.config)
|
||||
},
|
||||
mounted() {
|
||||
// Handle VueFileManager width
|
||||
var VueFileManager = document.getElementById('vue-file-manager');
|
||||
new ResizeSensor(VueFileManager, this.handleAppResize);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
* {
|
||||
outline: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Nunito', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
// Dark mode support
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
body, html {
|
||||
background: $dark_mode_background;
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
img {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#auth {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#vue-file-manager {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'AuthContentWrapper',
|
||||
}
|
||||
@@ -18,8 +17,5 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: table;
|
||||
//display: flex;
|
||||
//align-items: center;
|
||||
//justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,32 +1,29 @@
|
||||
<template>
|
||||
<transition name="vignette">
|
||||
<div class="popup" v-show="isVisibleWrapper">
|
||||
<transition name="popup">
|
||||
<div v-show="isVisiblePopup" class="popup-wrapper">
|
||||
<div class="popup-image">
|
||||
<span class="emoji">{{ emoji }}</span>
|
||||
</div>
|
||||
<div class="popup-content">
|
||||
<h1 v-if="title" class="title">{{ title }}</h1>
|
||||
<p v-if="message" class="message">{{ message }}</p>
|
||||
</div>
|
||||
<div class="popup-actions">
|
||||
<ButtonBase
|
||||
@click.native="closePopup"
|
||||
:button-style="buttonStyle"
|
||||
class="action-confirm"
|
||||
>{{ button }}
|
||||
</ButtonBase>
|
||||
</div>
|
||||
<transition name="popup">
|
||||
<div @click.self="closePopup" class="popup" v-if="isVisibleWrapper">
|
||||
<div class="popup-wrapper">
|
||||
<div class="popup-image">
|
||||
<span class="emoji">{{ emoji }}</span>
|
||||
</div>
|
||||
</transition>
|
||||
<div class="popup-vignette" @click="closePopup"></div>
|
||||
<div class="popup-content">
|
||||
<h1 v-if="title" class="title">{{ title }}</h1>
|
||||
<p v-if="message" class="message">{{ message }}</p>
|
||||
</div>
|
||||
<div class="popup-actions">
|
||||
<ButtonBase
|
||||
@click.native="closePopup"
|
||||
:button-style="buttonStyle"
|
||||
class="action-confirm"
|
||||
>{{ button }}
|
||||
</ButtonBase>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonBase from '@/components/VueFileManagerComponents/FilesView/ButtonBase'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
@@ -38,7 +35,6 @@
|
||||
return {
|
||||
isVisibleWrapper: false,
|
||||
buttonStyle: undefined,
|
||||
isVisiblePopup: false,
|
||||
message: undefined,
|
||||
title: undefined,
|
||||
button: undefined,
|
||||
@@ -47,26 +43,20 @@
|
||||
},
|
||||
methods: {
|
||||
closePopup() {
|
||||
// Emit event
|
||||
events.$emit('alert:close')
|
||||
|
||||
// Hide popup wrapper
|
||||
this.isVisibleWrapper = false
|
||||
this.isVisiblePopup = false
|
||||
events.$emit('popup:close')
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// Show alert
|
||||
events.$on('alert:open', args => {
|
||||
this.isVisibleWrapper = true
|
||||
this.isVisiblePopup = true
|
||||
|
||||
this.title = args.title
|
||||
this.message = args.message
|
||||
|
||||
this.button = 'That’s horrible!'
|
||||
this.button = this.$t('alerts.error_confirm')
|
||||
this.emoji = '😢😢😢'
|
||||
this.buttonStyle = 'danger'
|
||||
this.buttonStyle = 'danger-solid'
|
||||
|
||||
if (args.emoji) {
|
||||
this.emoji = args.emoji
|
||||
@@ -76,12 +66,11 @@
|
||||
// Show alert
|
||||
events.$on('success:open', args => {
|
||||
this.isVisibleWrapper = true
|
||||
this.isVisiblePopup = true
|
||||
|
||||
this.title = args.title
|
||||
this.message = args.message
|
||||
|
||||
this.button = 'Awesome!'
|
||||
this.button = this.$t('alerts.success_confirm')
|
||||
this.emoji = '🥳🥳🥳'
|
||||
this.buttonStyle = 'theme'
|
||||
|
||||
@@ -92,7 +81,6 @@
|
||||
|
||||
// Close popup
|
||||
events.$on('popup:close', () => {
|
||||
this.isVisiblePopup = false
|
||||
this.isVisibleWrapper = false
|
||||
})
|
||||
}
|
||||
@@ -110,15 +98,7 @@
|
||||
bottom: 0;
|
||||
z-index: 20;
|
||||
overflow: auto;
|
||||
|
||||
.popup-vignette {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.popup-wrapper {
|
||||
@@ -130,8 +110,8 @@
|
||||
top: 50%;
|
||||
transform: translateY(-50%) scale(1);
|
||||
margin: 0 auto;
|
||||
padding: 40px;
|
||||
box-shadow: 0 7px 250px rgba(25, 54, 60, 0.2);
|
||||
padding: 20px;
|
||||
box-shadow: $light_mode_popup_shadow;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
background: white;
|
||||
@@ -156,7 +136,7 @@
|
||||
|
||||
.message {
|
||||
@include font-size(16);
|
||||
color: #8b8f9a;
|
||||
color: #333;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
@@ -180,12 +160,8 @@
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.popup .popup-vignette {
|
||||
background: $dark_mode_vignette;
|
||||
}
|
||||
|
||||
.popup-wrapper {
|
||||
background: $dark_mode_foreground;
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
@@ -211,28 +187,11 @@
|
||||
@keyframes popup-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-50%) scale(0.7);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.vignette-enter-active {
|
||||
animation: vignette-in 0.15s ease;
|
||||
}
|
||||
|
||||
.vignette-leave-active {
|
||||
animation: vignette-in 0.15s 0.15s ease reverse;
|
||||
}
|
||||
|
||||
@keyframes vignette-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,16 @@
|
||||
<template>
|
||||
<button class="button-base" :class="buttonStyle" type="button">
|
||||
<slot></slot>
|
||||
<span v-if="loading" class="icon">
|
||||
<FontAwesomeIcon icon="sync-alt" class="sync-alt"/>
|
||||
</span>
|
||||
<slot v-if="! loading"></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ButtonBase',
|
||||
props: ['buttonStyle']
|
||||
props: ['buttonStyle', 'loading']
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -16,7 +19,7 @@
|
||||
|
||||
.button-base {
|
||||
@include font-size(16);
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: 0.15s all ease;
|
||||
border-radius: 8px;
|
||||
@@ -38,12 +41,30 @@
|
||||
background: rgba($danger, .1);
|
||||
}
|
||||
|
||||
&.danger-solid {
|
||||
color: white;
|
||||
background: $danger;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: $text;
|
||||
background: $light_background;
|
||||
}
|
||||
}
|
||||
|
||||
.sync-alt {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.button-base {
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
.button-base {
|
||||
@include font-size(16);
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: 0.15s all ease;
|
||||
border-radius: 8px;
|
||||
280
resources/js/components/FilesView/ContextMenu.vue
Normal file
280
resources/js/components/FilesView/ContextMenu.vue
Normal file
@@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<div
|
||||
:style="{ top: positionY + 'px', left: positionX + 'px' }"
|
||||
@click="closeAndResetContextMenu"
|
||||
class="contextmenu"
|
||||
v-show="isVisible"
|
||||
ref="contextmenu"
|
||||
>
|
||||
<!--ContextMenu for trash location-->
|
||||
<ul v-if="$isThisLocation(['trash', 'trash-root']) && $checkPermission('master')" class="menu-options" ref="list">
|
||||
<li class="menu-option" @click="deleteItem" v-if="item">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="$store.dispatch('restoreItem', item)" v-if="item">
|
||||
{{ $t('context_menu.restore') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="$store.dispatch('emptyTrash')">
|
||||
{{ $t('context_menu.empty_trash') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="ItemDetail" v-if="item">
|
||||
{{ $t('context_menu.detail') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder && item">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--ContextMenu for Base location with MASTER permission-->
|
||||
<ul v-if="$isThisLocation(['shared']) && $checkPermission('master')" class="menu-options" ref="list">
|
||||
<li class="menu-option" @click="addToFavourites" v-if="item && isFolder">
|
||||
{{ isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="deleteItem" v-if="item">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="shareItem" v-if="item">
|
||||
{{ item.shared ? $t('context_menu.share_edit') : $t('context_menu.share') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="ItemDetail" v-if="item">
|
||||
{{ $t('context_menu.detail') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder && item">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--ContextMenu for Base location with MASTER permission-->
|
||||
<ul v-if="$isThisLocation(['base']) && $checkPermission('master')" class="menu-options" ref="list">
|
||||
<li class="menu-option" @click="addToFavourites" v-if="item && isFolder">
|
||||
{{ isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="createFolder">
|
||||
{{ $t('context_menu.create_folder') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="deleteItem" v-if="item">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem" v-if="item">
|
||||
{{ $t('context_menu.move') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="shareItem" v-if="item">
|
||||
{{ item.shared ? $t('context_menu.share_edit') : $t('context_menu.share') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="ItemDetail" v-if="item">
|
||||
{{ $t('context_menu.detail') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder && item">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--ContextMenu for Base location with EDITOR permission-->
|
||||
<ul v-if="$isThisLocation(['base', 'public']) && $checkPermission('editor')" class="menu-options" ref="list">
|
||||
<li class="menu-option" @click="createFolder">
|
||||
{{ $t('context_menu.create_folder') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="deleteItem" v-if="item">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem" v-if="item">
|
||||
{{ $t('context_menu.move') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="ItemDetail" v-if="item">
|
||||
{{ $t('context_menu.detail') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder && item">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--ContextMenu for Base location with VISITOR permission-->
|
||||
<ul v-if="$isThisLocation(['base', 'public']) && $checkPermission('visitor')" class="menu-options" ref="list">
|
||||
<li class="menu-option" @click="ItemDetail" v-if="item">
|
||||
{{ $t('context_menu.detail') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder && item">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'ContextMenu',
|
||||
computed: {
|
||||
...mapGetters(['app']),
|
||||
isFolder() {
|
||||
return this.item && this.item.type === 'folder'
|
||||
},
|
||||
isFile() {
|
||||
return (this.item && this.item.type !== 'folder') && (this.item && this.item.type !== 'image')
|
||||
},
|
||||
isImage() {
|
||||
return this.item && this.item.type === 'image'
|
||||
},
|
||||
isInFavourites() {
|
||||
return this.app.favourites.find(el => el.unique_id == this.item.unique_id)
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
item: undefined,
|
||||
isVisible: false,
|
||||
positionX: 0,
|
||||
positionY: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
moveItem() {
|
||||
// Open move item popup
|
||||
events.$emit('popup:open', {name: 'move', item: this.item})
|
||||
},
|
||||
shareItem() {
|
||||
if (this.item.shared) {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {name: 'share-edit', item: this.item})
|
||||
} else {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {name: 'share-create', item: this.item})
|
||||
}
|
||||
},
|
||||
addToFavourites() {
|
||||
// Check if folder is in favourites and then add/remove from favourites
|
||||
if (this.app.favourites && ! this.app.favourites.find(el => el.unique_id == this.item.unique_id)) {
|
||||
this.$store.dispatch('addToFavourites', this.item)
|
||||
} else {
|
||||
this.$store.dispatch('removeFromFavourites', this.item)
|
||||
}
|
||||
},
|
||||
downloadItem() {
|
||||
// Download file
|
||||
this.$downloadFile(
|
||||
this.item.file_url,
|
||||
this.item.name + '.' + this.item.mimetype
|
||||
)
|
||||
},
|
||||
ItemDetail() {
|
||||
// Dispatch load file info detail
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
|
||||
|
||||
// Show panel if is not open
|
||||
this.$store.dispatch('fileInfoToggle', true)
|
||||
},
|
||||
deleteItem() {
|
||||
// Dispatch remove item
|
||||
this.$store.dispatch('deleteItem', this.item)
|
||||
},
|
||||
createFolder() {
|
||||
// Create folder
|
||||
this.$createFolder(this.$t('popup_create_folder.folder_default_name'))
|
||||
},
|
||||
closeAndResetContextMenu() {
|
||||
// Close context menu
|
||||
this.isVisible = false
|
||||
|
||||
// Reset item container
|
||||
this.item = undefined
|
||||
},
|
||||
showContextMenu(event, item) {
|
||||
let VerticalOffsetArea = item && this.$refs.list.children ? this.$refs.list.children.length * 50 : 50
|
||||
let HorizontalOffsetArea = 190
|
||||
|
||||
let container = document.getElementById('files-view')
|
||||
|
||||
var offset = container.getClientRects()[0];
|
||||
|
||||
let x = event.clientX - offset.left
|
||||
let y = event.clientY - offset.top
|
||||
|
||||
// Set position Y
|
||||
if ((container.offsetHeight - y) < VerticalOffsetArea) {
|
||||
this.positionY = y - VerticalOffsetArea
|
||||
} else {
|
||||
this.positionY = y
|
||||
}
|
||||
|
||||
// Set position X
|
||||
if ((container.offsetWidth - x) < HorizontalOffsetArea) {
|
||||
this.positionX = x - HorizontalOffsetArea
|
||||
} else {
|
||||
this.positionX = x
|
||||
}
|
||||
|
||||
// Show context menu
|
||||
this.isVisible = true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
events.$on('contextMenu:show', (event, item) => {
|
||||
|
||||
// Store item
|
||||
this.item = item
|
||||
|
||||
// Show context menu
|
||||
setTimeout(() => this.showContextMenu(event, item), 10)
|
||||
})
|
||||
|
||||
events.$on('contextMenu:hide', () => (this.closeAndResetContextMenu()))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.contextmenu {
|
||||
min-width: 190px;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
box-shadow: $shadow;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu-options {
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.menu-option {
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
@include font-size(15);
|
||||
padding: 15px 30px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
color: $text;
|
||||
|
||||
&:hover {
|
||||
background: $light_background;
|
||||
color: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.contextmenu {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
.menu-options .menu-option {
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
&:hover {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div id="desktop-toolbar">
|
||||
<div id="desktop-toolbar" v-if="! $isMinimalScale()">
|
||||
<div class="toolbar-wrapper">
|
||||
|
||||
<!-- Go back-->
|
||||
<div class="toolbar-go-back" v-if="homeDirectory">
|
||||
<div @click="goBack" class="go-back-button">
|
||||
@@ -9,34 +10,43 @@
|
||||
class="icon-back"
|
||||
icon="chevron-left"
|
||||
></FontAwesomeIcon>
|
||||
<span class="back-directory-title">{{
|
||||
directoryName
|
||||
}}</span>
|
||||
<span class="back-directory-title">
|
||||
{{ directoryName }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tools-->
|
||||
<div class="toolbar-tools">
|
||||
|
||||
<!--Search bar-->
|
||||
<div class="toolbar-button-wrapper">
|
||||
<SearchBar/>
|
||||
</div>
|
||||
<div class="toolbar-button-wrapper">
|
||||
<ToolbarButtonUpload source="upload" action="Upload file"/>
|
||||
|
||||
<!--Files controlls-->
|
||||
<div class="toolbar-button-wrapper" v-if="$checkPermission(['master', 'editor'])">
|
||||
<ToolbarButtonUpload
|
||||
source="upload"
|
||||
:action="$t('actions.upload')"
|
||||
/>
|
||||
<ToolbarButton
|
||||
source="trash-alt"
|
||||
action="Delete"
|
||||
:action="$t('actions.delete')"
|
||||
@click.native="deleteItems"
|
||||
/>
|
||||
<ToolbarButton
|
||||
@click.native="createFolder"
|
||||
source="folder-plus"
|
||||
action="Create folder"
|
||||
:action="$t('actions.create_folder')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!--View options-->
|
||||
<div class="toolbar-button-wrapper">
|
||||
<ToolbarButton
|
||||
:source="preview"
|
||||
action=""
|
||||
:action="$t('actions.preview')"
|
||||
@click.native="$store.dispatch('changePreviewType')"
|
||||
/>
|
||||
<ToolbarButton
|
||||
@@ -52,10 +62,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ToolbarButtonUpload from '@/components/VueFileManagerComponents/FilesView/ToolbarButtonUpload'
|
||||
import UploadProgress from '@/components/VueFileManagerComponents/FilesView/UploadProgress'
|
||||
import ToolbarButton from '@/components/VueFileManagerComponents/FilesView/ToolbarButton'
|
||||
import SearchBar from '@/components/VueFileManagerComponents/FilesView/SearchBar'
|
||||
import ToolbarButtonUpload from '@/components/FilesView/ToolbarButtonUpload'
|
||||
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'
|
||||
|
||||
@@ -74,7 +84,7 @@
|
||||
'currentFolder',
|
||||
'browseHistory',
|
||||
'homeDirectory',
|
||||
'preview_type',
|
||||
'FilePreviewType',
|
||||
]),
|
||||
directoryName() {
|
||||
return this.currentFolder ? this.currentFolder.name : this.homeDirectory.name
|
||||
@@ -85,8 +95,8 @@
|
||||
return this.browseHistory[length] ? this.browseHistory[length] : this.homeDirectory
|
||||
},
|
||||
preview() {
|
||||
return this.preview_type === 'list' ? 'th' : 'th-list'
|
||||
}
|
||||
return this.FilePreviewType === 'list' ? 'th' : 'th-list'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -105,14 +115,19 @@
|
||||
this.$store.commit('FLUSH_BROWSER_HISTORY')
|
||||
|
||||
} else {
|
||||
this.$store.dispatch('goToFolder', [this.previousFolder, true])
|
||||
if ( this.$isThisLocation('public') ) {
|
||||
this.$store.dispatch('browseShared', [this.previousFolder, true])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.previousFolder, true])
|
||||
}
|
||||
}
|
||||
},
|
||||
deleteItems() {
|
||||
events.$emit('items:delete')
|
||||
},
|
||||
createFolder() {
|
||||
this.$createFolder()
|
||||
if (! this.$isThisLocation(['trash', 'trash-root']))
|
||||
this.$createFolder()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -136,7 +151,6 @@
|
||||
z-index: 2;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
white-space: nowrap;
|
||||
@@ -147,7 +161,7 @@
|
||||
vertical-align: middle;
|
||||
@include font-size(17);
|
||||
color: $text;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
max-width: 220px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -165,7 +179,7 @@
|
||||
|
||||
.back-directory-title {
|
||||
line-height: 1;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
55
resources/js/components/FilesView/EmptyMessage.vue
Normal file
55
resources/js/components/FilesView/EmptyMessage.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="empty-message">
|
||||
<div class="message">
|
||||
<FontAwesomeIcon class="icon" :icon="icon"/>
|
||||
<p>{{ message }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'EmptyMessage',
|
||||
props: ['icon', 'message']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.empty-message {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
.message {
|
||||
margin: 0 auto;
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
max-width: 130px;
|
||||
@include font-size(14);
|
||||
font-weight: 500;
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@include font-size(36);
|
||||
color: $text;
|
||||
|
||||
path {
|
||||
fill: $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.empty-message .message .icon {
|
||||
path {
|
||||
fill: $dark_mode_text_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,20 +1,31 @@
|
||||
<template>
|
||||
<div class="empty-page" v-if="isLoading || isEmpty">
|
||||
<div class="empty-state">
|
||||
<div class="text-content" v-if="isEmpty && !isLoading">
|
||||
<h1 class="title">There is Nothing</h1>
|
||||
<p v-if="! isTrash" class="description">
|
||||
Upload some files here easily via upload button
|
||||
</p>
|
||||
<ButtonUpload
|
||||
v-if="! isTrash"
|
||||
@input.native="$uploadFiles(files)"
|
||||
v-model="files"
|
||||
button-style="theme"
|
||||
>Upload File
|
||||
</ButtonUpload
|
||||
>
|
||||
|
||||
<!--Shared empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['shared']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('shared.empty_shared') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Trash empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['trash', 'trash-root']) && ! isLoading">
|
||||
<h1 class="title">{{ $t('empty_page.title') }}</h1>
|
||||
</div>
|
||||
|
||||
<!--Base file browser empty message-->
|
||||
<div class="text-content" v-if="$isThisLocation(['base', 'public']) && !isLoading">
|
||||
<h1 class="title">{{ $t('empty_page.title') }}</h1>
|
||||
<p v-if="$checkPermission(['master', 'editor'])" class="description">{{ $t('empty_page.description') }}</p>
|
||||
<ButtonUpload
|
||||
v-if="$checkPermission(['master', 'editor'])"
|
||||
@input.native="$uploadFiles"
|
||||
button-style="theme"
|
||||
>
|
||||
{{ $t('empty_page.call_to_action') }}
|
||||
</ButtonUpload>
|
||||
</div>
|
||||
|
||||
<!--Spinner-->
|
||||
<div class="text-content" v-if="isLoading">
|
||||
<Spinner/>
|
||||
</div>
|
||||
@@ -23,8 +34,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonUpload from '@/components/VueFileManagerComponents/FilesView/ButtonUpload'
|
||||
import Spinner from '@/components/VueFileManagerComponents/FilesView/Spinner'
|
||||
import ButtonUpload from '@/components/FilesView/ButtonUpload'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
@@ -37,15 +48,7 @@
|
||||
computed: {
|
||||
...mapGetters(['data', 'isLoading', 'currentFolder']),
|
||||
isEmpty() {
|
||||
return this.data.length == 0
|
||||
},
|
||||
isTrash() {
|
||||
return typeof this.currentFolder.unique_id === 'undefined'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
files: undefined
|
||||
return this.data && this.data.length == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,7 +81,7 @@
|
||||
.title {
|
||||
@include font-size(24);
|
||||
color: $text;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
<template>
|
||||
<div class="file-content" :class="{ 'is-offset': uploadingFilesCount }">
|
||||
<div class="file-content" :class="{ 'is-offset': uploadingFilesCount, 'is-dragging': isDragging }"
|
||||
@dragover.prevent
|
||||
@drop.stop.prevent="dropUpload($event)"
|
||||
@dragover="dragEnter"
|
||||
@dragleave="dragLeave"
|
||||
>
|
||||
<div
|
||||
class="files-container"
|
||||
ref="fileContainer"
|
||||
:class="{
|
||||
'is-fileinfo-visible': fileInfoVisible && !$isMinimalScale()
|
||||
}"
|
||||
:class="{'is-fileinfo-visible': fileInfoVisible && !$isMinimalScale() }"
|
||||
@click.self="filesContainerClick"
|
||||
>
|
||||
<!--MobileToolbar-->
|
||||
<MobileToolbar v-if="$isMinimalScale()"/>
|
||||
<MobileToolbar />
|
||||
|
||||
<!--Searchbar-->
|
||||
<SearchBar v-if="$isMinimalScale()" class="mobile-search"/>
|
||||
|
||||
<!--Mobile Actions-->
|
||||
<MobileActions v-if="$isMinimalScale()" />
|
||||
<MobileActions />
|
||||
|
||||
<!--Item previews list-->
|
||||
<div v-if="isList" class="file-list-wrapper">
|
||||
@@ -23,12 +26,11 @@
|
||||
name="file"
|
||||
tag="section"
|
||||
class="file-list"
|
||||
:class="preview_type"
|
||||
:class="FilePreviewType"
|
||||
>
|
||||
<FileItemList
|
||||
@dragstart="dragStart(item)"
|
||||
@drop="dragFinish(item)"
|
||||
@click.native="clickedFileItem(item.unique_id)"
|
||||
@drop.stop.native.prevent="dragFinish(item, $event)"
|
||||
@contextmenu.native.prevent="contextMenu($event, item)"
|
||||
:data="item"
|
||||
v-for="item in data"
|
||||
@@ -44,12 +46,11 @@
|
||||
name="file"
|
||||
tag="section"
|
||||
class="file-list"
|
||||
:class="preview_type"
|
||||
:class="FilePreviewType"
|
||||
>
|
||||
<FileItemGrid
|
||||
@dragstart="dragStart(item)"
|
||||
@drop="dragFinish(item)"
|
||||
@click.native="clickedFileItem(item.unique_id)"
|
||||
@drop.native.prevent="dragFinish(item, $event)"
|
||||
@contextmenu.native.prevent="contextMenu($event, item)"
|
||||
:data="item"
|
||||
v-for="item in data"
|
||||
@@ -60,43 +61,36 @@
|
||||
</div>
|
||||
|
||||
<!--Show empty page if folder is empty-->
|
||||
<EmptyPage v-if="!isSearching"/>
|
||||
<EmptyPage v-if="! isSearching"/>
|
||||
|
||||
<!--Show empty page if no search results-->
|
||||
<EmptyMessage
|
||||
v-if="isSearching && isEmpty"
|
||||
message="Nothing was found."
|
||||
:message="$t('messages.nothing_was_found')"
|
||||
icon="eye-slash"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="!$isMinimalScale()"
|
||||
class="file-info-container"
|
||||
:class="{ 'is-fileinfo-visible': fileInfoVisible }"
|
||||
>
|
||||
<!--File Info Panel-->
|
||||
<div v-if="! $isMinimalScale()" class="file-info-container" :class="{ 'is-fileinfo-visible': fileInfoVisible }">
|
||||
<!--File info panel-->
|
||||
<FileInfoPanel v-if="fileInfoDetail"/>
|
||||
|
||||
<!--If file info panel empty show message-->
|
||||
<EmptyMessage
|
||||
v-if="!fileInfoDetail"
|
||||
message="There is nothing to preview."
|
||||
icon="eye-slash"
|
||||
/>
|
||||
<EmptyMessage v-if="!fileInfoDetail" :message="$t('messages.nothing_to_preview')" icon="eye-slash"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MobileToolbar from '@/components/VueFileManagerComponents/FilesView/MobileToolbar'
|
||||
import MobileActions from '@/components/VueFileManagerComponents/FilesView/MobileActions'
|
||||
import FileInfoPanel from '@/components/VueFileManagerComponents/FilesView/FileInfoPanel'
|
||||
import FileItemList from '@/components/VueFileManagerComponents/FilesView/FileItemList'
|
||||
import FileItemGrid from '@/components/VueFileManagerComponents/FilesView/FileItemGrid'
|
||||
import EmptyMessage from '@/components/VueFileManagerComponents/FilesView/EmptyMessage'
|
||||
import EmptyPage from '@/components/VueFileManagerComponents/FilesView/EmptyPage'
|
||||
import SearchBar from '@/components/VueFileManagerComponents/FilesView/SearchBar'
|
||||
import MobileToolbar from '@/components/FilesView/MobileToolbar'
|
||||
import MobileActions from '@/components/FilesView/MobileActions'
|
||||
import FileInfoPanel from '@/components/FilesView/FileInfoPanel'
|
||||
import FileItemList from '@/components/FilesView/FileItemList'
|
||||
import FileItemGrid from '@/components/FilesView/FileItemGrid'
|
||||
import EmptyMessage from '@/components/FilesView/EmptyMessage'
|
||||
import EmptyPage from '@/components/FilesView/EmptyPage'
|
||||
import SearchBar from '@/components/FilesView/SearchBar'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
@@ -118,16 +112,16 @@
|
||||
'fileInfoVisible',
|
||||
'fileInfoDetail',
|
||||
'currentFolder',
|
||||
'preview_type',
|
||||
'FilePreviewType',
|
||||
'isSearching',
|
||||
'isLoading',
|
||||
'data'
|
||||
]),
|
||||
isGrid() {
|
||||
return this.preview_type === 'grid'
|
||||
return this.FilePreviewType === 'grid'
|
||||
},
|
||||
isList() {
|
||||
return this.preview_type === 'list'
|
||||
return this.FilePreviewType === 'list'
|
||||
},
|
||||
isEmpty() {
|
||||
return this.data.length == 0
|
||||
@@ -135,10 +129,23 @@
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
draggingId: undefined
|
||||
draggingId: undefined,
|
||||
isDragging: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dropUpload(event) {
|
||||
// Upload external file
|
||||
this.$uploadExternalFiles(event, this.currentFolder.unique_id)
|
||||
|
||||
this.isDragging = false
|
||||
},
|
||||
dragEnter() {
|
||||
this.isDragging = true
|
||||
},
|
||||
dragLeave() {
|
||||
this.isDragging = false
|
||||
},
|
||||
dragStart(data) {
|
||||
|
||||
events.$emit('dragstart', data)
|
||||
@@ -146,26 +153,36 @@
|
||||
// Store dragged folder
|
||||
this.draggingId = data
|
||||
},
|
||||
dragFinish(data) {
|
||||
// Prevent to drop on file or image
|
||||
if (data.type !== 'folder' || this.draggingId === data) return
|
||||
dragFinish(data, event) {
|
||||
|
||||
// Move folder to new parent
|
||||
this.moveTo(this.draggingId, data)
|
||||
},
|
||||
moveTo(from_item, to_item) {
|
||||
this.$store.dispatch('moveItem', [from_item, to_item])
|
||||
},
|
||||
clickedFileItem(unique_id) {
|
||||
events.$emit('fileItem:clicked', unique_id)
|
||||
if (event.dataTransfer.items.length == 0) {
|
||||
|
||||
// Prevent to drop on file or image
|
||||
if (data.type !== 'folder' || this.draggingId === data) return
|
||||
|
||||
// Move folder to new parent
|
||||
this.$store.dispatch('moveItem', [this.draggingId, data])
|
||||
|
||||
} else {
|
||||
|
||||
// Get unique_id of current folder
|
||||
const unique_id = data.type !== 'folder' ? this.currentFolder.unique_id : data.unique_id
|
||||
|
||||
// Upload external file
|
||||
this.$uploadExternalFiles(event, unique_id)
|
||||
}
|
||||
|
||||
this.isDragging = false
|
||||
},
|
||||
contextMenu(event, item) {
|
||||
events.$emit('contextMenu:show', event, item)
|
||||
},
|
||||
filesContainerClick(e) {
|
||||
if (e.target.className === 'file-list grid') {
|
||||
events.$emit('fileItem:deselect')
|
||||
}
|
||||
filesContainerClick() {
|
||||
|
||||
// Deselect clicked item
|
||||
events.$emit('fileItem:deselect')
|
||||
|
||||
// Hide context menu if is opened
|
||||
events.$emit('contextMenu:hide')
|
||||
}
|
||||
},
|
||||
@@ -185,27 +202,7 @@
|
||||
|
||||
// On items delete
|
||||
events.$on('items:delete', () => {
|
||||
this.$store.dispatch('removeItem', this.fileInfoDetail)
|
||||
|
||||
//let ids = []
|
||||
//let items = []
|
||||
|
||||
// Get ids
|
||||
/*this.$children[0].$children.filter(item => {
|
||||
|
||||
if (item.isClicked) {
|
||||
|
||||
ids.push(item.data.unique_id)
|
||||
|
||||
items.push({
|
||||
unique_id: item.data.unique_id,
|
||||
type: item.data.type,
|
||||
})
|
||||
}
|
||||
})*/
|
||||
|
||||
// Dispatch action
|
||||
/*this.$store.dispatch('removeItems', [ids, items])*/
|
||||
this.$store.dispatch('deleteItem', this.fileInfoDetail)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -228,6 +225,10 @@
|
||||
.file-content {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
&.is-dragging {
|
||||
@include transform(scale(0.99));
|
||||
}
|
||||
}
|
||||
|
||||
.files-container {
|
||||
@@ -278,4 +279,10 @@
|
||||
.file-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 660px) {
|
||||
.file-info-container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
329
resources/js/components/FilesView/FileInfoPanel.vue
Normal file
329
resources/js/components/FilesView/FileInfoPanel.vue
Normal file
@@ -0,0 +1,329 @@
|
||||
<template>
|
||||
<div class="file-info-content" v-if="fileInfoDetail">
|
||||
<div class="file-headline" spellcheck="false">
|
||||
<FilePreview />
|
||||
|
||||
<!--File info-->
|
||||
<div class="flex">
|
||||
<div class="icon">
|
||||
<div class="icon-preview">
|
||||
<FontAwesomeIcon :icon="filePreviewIcon"></FontAwesomeIcon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<span ref="name" class="name">{{ fileInfoDetail.name }}</span>
|
||||
<span class="mimetype" v-if="fileInfoDetail.mimetype">{{ fileInfoDetail.mimetype }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Info list-->
|
||||
<ul class="list-info">
|
||||
|
||||
<!--Filesize-->
|
||||
<li v-if="fileInfoDetail.filesize" class="list-info-item">
|
||||
<b>{{ $t('file_detail.size') }}</b>
|
||||
<span>{{ fileInfoDetail.filesize }}</span>
|
||||
</li>
|
||||
|
||||
<!--Latest change-->
|
||||
<li v-if="$checkPermission(['master']) && fileInfoDetail.user_scope !== 'master'" class="list-info-item">
|
||||
<b>{{ $t('file_detail.author') }}</b>
|
||||
<span>{{ $t('file_detail.author_participant') }}</span>
|
||||
</li>
|
||||
|
||||
<!--Latest change-->
|
||||
<li class="list-info-item">
|
||||
<b>{{ $t('file_detail.created_at') }}</b>
|
||||
<span>{{ fileInfoDetail.created_at }}</span>
|
||||
</li>
|
||||
|
||||
<!--Parent-->
|
||||
<li v-if="$checkPermission(['master'])" class="list-info-item">
|
||||
<b>{{ $t('file_detail.where') }}</b>
|
||||
<div class="action-button" @click="moveItem">
|
||||
<FontAwesomeIcon class="icon" icon="pencil-alt" />
|
||||
<span>{{ fileInfoDetail.parent ? fileInfoDetail.parent.name : $t('locations.home') }}</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!--Parent-->
|
||||
<li v-if="$checkPermission('master') && fileInfoDetail.shared" class="list-info-item">
|
||||
<b>{{ $t('file_detail.shared') }}</b>
|
||||
<div class="action-button" @click="shareItemOptions">
|
||||
<FontAwesomeIcon class="icon" :icon="sharedIcon" />
|
||||
<span>{{ sharedInfo }}</span>
|
||||
</div>
|
||||
<div class="sharelink">
|
||||
<FontAwesomeIcon class="lock-icon" :icon="lockIcon" @click="shareItemOptions" />
|
||||
<CopyInput class="copy-sharelink" size="small" :value="fileInfoDetail.shared.link" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilePreview from '@/components/FilesView/FilePreview'
|
||||
import CopyInput from '@/components/Others/Forms/CopyInput'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
|
||||
export default {
|
||||
name: 'FileInfoPanel',
|
||||
components: {
|
||||
FilePreview,
|
||||
CopyInput,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'permissionOptions']),
|
||||
filePreviewIcon() {
|
||||
switch (this.fileInfoDetail.type) {
|
||||
case 'folder':
|
||||
return 'folder'
|
||||
break;
|
||||
case 'file':
|
||||
return 'file'
|
||||
break;
|
||||
case 'image':
|
||||
return 'file-image'
|
||||
break;
|
||||
case 'video':
|
||||
return 'file-video'
|
||||
break;
|
||||
case 'file':
|
||||
return 'file-audio'
|
||||
break;
|
||||
}
|
||||
},
|
||||
sharedInfo() {
|
||||
|
||||
// Get permission title
|
||||
let title = this.permissionOptions.find(option => {
|
||||
return option.value === this.fileInfoDetail.shared.permission
|
||||
})
|
||||
|
||||
return title ? title.label : this.$t('shared.can_download')
|
||||
},
|
||||
sharedIcon() {
|
||||
switch (this.fileInfoDetail.shared.permission) {
|
||||
case 'editor':
|
||||
return 'user-edit'
|
||||
break
|
||||
case 'visitor':
|
||||
return 'user'
|
||||
break
|
||||
default:
|
||||
return 'download'
|
||||
}
|
||||
},
|
||||
lockIcon() {
|
||||
return this.fileInfoDetail.shared.protected ? 'lock' : 'lock-open'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
shareItemOptions() {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {name: 'share-edit', item: this.fileInfoDetail})
|
||||
},
|
||||
moveItem() {
|
||||
// Move item fire popup
|
||||
events.$emit('popup:open', {name: 'move', item: this.fileInfoDetail})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.file-info-content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.file-headline {
|
||||
background: $light_background;
|
||||
padding: 12px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 8px;
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.icon-preview {
|
||||
height: 42px;
|
||||
width: 42px;
|
||||
border-radius: 8px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
background: white;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
outline: none;
|
||||
border: none;
|
||||
|
||||
/deep/ svg {
|
||||
@include font-size(22);
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-info {
|
||||
padding-left: 12px;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
|
||||
.name {
|
||||
@include font-size(14);
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
display: block;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.mimetype {
|
||||
@include font-size(14);
|
||||
font-weight: 600;
|
||||
color: $theme;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-info {
|
||||
padding-left: 12px;
|
||||
|
||||
.list-info-item {
|
||||
display: block;
|
||||
padding-top: 15px;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
@include font-size(10);
|
||||
display: inline-block;
|
||||
margin-right: 2px;
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b {
|
||||
display: block;
|
||||
@include font-size(13);
|
||||
color: $theme;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
@include font-size(14);
|
||||
font-weight: bold;
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sharelink {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
|
||||
.lock-icon {
|
||||
@include font-size(10);
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
margin-right: 9px;
|
||||
cursor: pointer;
|
||||
|
||||
path {
|
||||
fill: $text;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-sharelink {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.file-headline {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
.icon-preview {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
|
||||
.name {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-info {
|
||||
|
||||
.list-info-item {
|
||||
|
||||
span {
|
||||
color: $dark_mode_text_primary
|
||||
}
|
||||
|
||||
.action-button {
|
||||
|
||||
.icon {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sharelink {
|
||||
|
||||
.lock-icon {
|
||||
|
||||
path {
|
||||
fill: $dark_mode_text_primary;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -7,7 +7,7 @@
|
||||
>
|
||||
<!--Grid preview-->
|
||||
<div
|
||||
draggable="true"
|
||||
:draggable="canDrag"
|
||||
@dragstart="$emit('dragstart')"
|
||||
@drop="
|
||||
$emit('drop')
|
||||
@@ -19,51 +19,61 @@
|
||||
:class="{ 'is-clicked': isClicked, 'is-dragenter': area }"
|
||||
>
|
||||
<!--Thumbnail for item-->
|
||||
<div class="icon-item" :class="data.type">
|
||||
<div class="icon-item">
|
||||
|
||||
<!--If is file or image, then link item-->
|
||||
<span v-if="isFile" class="file-icon-text">{{
|
||||
data.mimetype
|
||||
}}</span>
|
||||
<span v-if="isFile" class="file-icon-text">
|
||||
{{ data.mimetype }}
|
||||
</span>
|
||||
|
||||
<!--Folder thumbnail-->
|
||||
<FontAwesomeIcon v-if="isFile" class="file-icon" icon="file"/>
|
||||
|
||||
<!--Image thumbnail-->
|
||||
<img v-if="isImage" :src="data.thumbnail" :alt="data.name"/>
|
||||
<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"
|
||||
/>
|
||||
<FontAwesomeIcon v-if="isFolder" :class="{'is-deleted': isDeleted}" class="folder-icon" icon="folder"/>
|
||||
</div>
|
||||
|
||||
<!--Name-->
|
||||
<div class="item-name">
|
||||
<!--Name-->
|
||||
<span
|
||||
<b
|
||||
ref="name"
|
||||
@input="changeItemName"
|
||||
:contenteditable="!$isMobile()"
|
||||
@input="renameItem"
|
||||
:contenteditable="canEditName"
|
||||
class="name"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
{{ itemName }}
|
||||
</b>
|
||||
|
||||
<!--Other attributes-->
|
||||
<span v-if="isFile || isImage" class="item-size">{{
|
||||
data.filesize
|
||||
}}</span>
|
||||
<div class="item-info">
|
||||
|
||||
<span v-if="isFolder" class="item-length">
|
||||
{{ folderItems == 0 ? 'Empty' : (folderItems + ' item') | pluralize(folderItems) }}
|
||||
</span>
|
||||
<!--Shared Icon-->
|
||||
<div v-if="$checkPermission('master') && data.shared" class="item-shared">
|
||||
<FontAwesomeIcon class="shared-icon" icon="share"/>
|
||||
</div>
|
||||
|
||||
<!--Participant owner Icon-->
|
||||
<div v-if="$checkPermission('master') && data.user_scope !== 'master'" class="item-shared">
|
||||
<FontAwesomeIcon class="shared-icon" icon="user-edit"/>
|
||||
</div>
|
||||
|
||||
<!--Filesize-->
|
||||
<span v-if="! isFolder" class="item-size">{{ data.filesize }}</span>
|
||||
|
||||
<!--Folder item counts-->
|
||||
<span v-if="isFolder" class="item-length">
|
||||
{{ folderItems == 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span @click.stop="showItemActions" class="show-actions" v-if="$isMobile()">
|
||||
<FontAwesomeIcon icon="ellipsis-h" class="icon-action"></FontAwesomeIcon>
|
||||
</span>
|
||||
<span @click.stop="showItemActions" class="show-actions"
|
||||
v-if="$isMobile() && ! ( $checkPermission('visitor') && isFolder ) && canShowMobileOptions">
|
||||
<FontAwesomeIcon icon="ellipsis-h" class="icon-action"></FontAwesomeIcon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -74,21 +84,35 @@
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'FileItem',
|
||||
name: 'FileItemGrid',
|
||||
props: ['data'],
|
||||
computed: {
|
||||
...mapGetters(['preview_type']),
|
||||
...mapGetters([
|
||||
'FilePreviewType', 'sharedDetail'
|
||||
]),
|
||||
isFolder() {
|
||||
return this.data.type === 'folder'
|
||||
},
|
||||
isFile() {
|
||||
return this.data.type === 'file'
|
||||
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')
|
||||
},
|
||||
canShowMobileOptions() {
|
||||
return ! (this.sharedDetail && this.sharedDetail.type === 'file')
|
||||
},
|
||||
canDrag() {
|
||||
return !this.isDeleted && this.$checkPermission(['master', 'editor'])
|
||||
},
|
||||
timeStamp() {
|
||||
return this.data.deleted_at ? 'Deleted ' + this.data.deleted_at : this.data.created_at
|
||||
return this.data.deleted_at ? this.$t('item_thumbnail.deleted_at', this.data.deleted_at) : this.data.created_at
|
||||
},
|
||||
folderItems() {
|
||||
return this.data.deleted_at ? this.data.trashed_items : this.data.items
|
||||
@@ -97,22 +121,17 @@
|
||||
return this.data.deleted_at ? true : false
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
pluralize(word, amount) {
|
||||
return amount > 1 ? word + 's' : word
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isClicked: false,
|
||||
area: false,
|
||||
item: undefined
|
||||
itemName: undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showItemActions() {
|
||||
// Load file info detail
|
||||
this.$store.dispatch('loadFileInfoDetail', this.data)
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
|
||||
|
||||
events.$emit('mobileMenu:show')
|
||||
},
|
||||
@@ -126,16 +145,24 @@
|
||||
},
|
||||
clickedItem(e) {
|
||||
events.$emit('contextMenu:hide')
|
||||
events.$emit('fileItem:deselect')
|
||||
|
||||
// Set clicked item
|
||||
this.isClicked = true
|
||||
|
||||
// Open in mobile version on first click
|
||||
if (this.$isMobile() && this.isFolder) {
|
||||
|
||||
// Go to folder
|
||||
this.$store.dispatch('goToFolder', [this.data, false])
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [this.data, false])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.data, false])
|
||||
}
|
||||
}
|
||||
|
||||
// Load file info detail
|
||||
this.$store.dispatch('loadFileInfoDetail', this.data)
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
|
||||
|
||||
// Get target classname
|
||||
let itemClass = e.target.className
|
||||
@@ -161,14 +188,19 @@
|
||||
|
||||
if (this.isFolder) {
|
||||
// Go to folder
|
||||
this.$store.dispatch('goToFolder', [this.data, false])
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [this.data, false])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.data, false])
|
||||
}
|
||||
}
|
||||
},
|
||||
changeItemName: debounce(function (e) {
|
||||
// Prevent submit empty string
|
||||
if (e.target.innerText === '') return
|
||||
renameItem: debounce(function (e) {
|
||||
|
||||
this.$store.dispatch('changeItemName', {
|
||||
// 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
|
||||
@@ -176,20 +208,17 @@
|
||||
}, 300)
|
||||
},
|
||||
created() {
|
||||
this.item = this.data
|
||||
|
||||
events.$on('fileItem:clicked', unique_id => {
|
||||
if (this.data.unique_id == unique_id) {
|
||||
this.isClicked = true
|
||||
} else {
|
||||
this.isClicked = false
|
||||
}
|
||||
})
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -210,7 +239,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.file-wrapper {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
@@ -227,26 +255,51 @@
|
||||
.item-size,
|
||||
.item-length {
|
||||
@include font-size(12);
|
||||
font-weight: 100;
|
||||
font-weight: 400;
|
||||
color: $text-muted;
|
||||
display: block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.name {
|
||||
.item-info {
|
||||
display: block;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&[contenteditable='true']:hover {
|
||||
text-decoration: underline;
|
||||
.item-shared {
|
||||
display: inline-block;
|
||||
|
||||
.label {
|
||||
@include font-size(12);
|
||||
font-weight: 400;
|
||||
color: $theme;
|
||||
}
|
||||
|
||||
.shared-icon {
|
||||
@include font-size(9);
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
color: $text;
|
||||
@include font-size(15);
|
||||
@include font-size(14);
|
||||
font-weight: 700;
|
||||
max-height: 40px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
|
||||
&[contenteditable] {
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
&[contenteditable='true']:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&.actived {
|
||||
max-height: initial;
|
||||
@@ -285,6 +338,7 @@
|
||||
}
|
||||
|
||||
.icon-item {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
height: 110px;
|
||||
margin-bottom: 20px;
|
||||
@@ -306,41 +360,34 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.file {
|
||||
|
||||
.file-icon-text {
|
||||
margin: 5px auto 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
color: $theme;
|
||||
font-weight: 600;
|
||||
user-select: none;
|
||||
max-width: 65px;
|
||||
max-height: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.file-icon-text {
|
||||
margin: 5px auto 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
color: $theme;
|
||||
font-weight: 600;
|
||||
user-select: none;
|
||||
max-width: 65px;
|
||||
max-height: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&.image {
|
||||
img {
|
||||
max-width: 95%;
|
||||
object-fit: cover;
|
||||
user-select: none;
|
||||
height: 110px;
|
||||
border-radius: 5px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.folder {
|
||||
align-items: flex-end;
|
||||
.image {
|
||||
max-width: 95%;
|
||||
object-fit: cover;
|
||||
user-select: none;
|
||||
height: 110px;
|
||||
border-radius: 5px;
|
||||
margin: 0 auto;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.folder-icon {
|
||||
align-items: flex-end;
|
||||
@include font-size(80);
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -388,4 +435,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div
|
||||
@click.stop="clickedItem" @dblclick="goToItem"
|
||||
class="file-wrapper"
|
||||
@click.stop="clickedItem"
|
||||
@dblclick="goToItem"
|
||||
spellcheck="false"
|
||||
>
|
||||
<!--List preview-->
|
||||
<div
|
||||
draggable="true"
|
||||
:draggable="canDrag"
|
||||
@dragstart="$emit('dragstart')"
|
||||
@drop="
|
||||
$emit('drop')
|
||||
@@ -18,48 +19,58 @@
|
||||
:class="{ 'is-clicked': isClicked, 'is-dragenter': area }"
|
||||
>
|
||||
<!--Thumbnail for item-->
|
||||
<div class="icon-item" :class="data.type">
|
||||
<div class="icon-item">
|
||||
<!--If is file or image, then link item-->
|
||||
<span v-if="isFile" class="file-icon-text">{{
|
||||
data.mimetype | limitCharacters
|
||||
}}</span>
|
||||
<span v-if="isFile" class="file-icon-text">
|
||||
{{ data.mimetype | limitCharacters }}
|
||||
</span>
|
||||
|
||||
<!--Folder thumbnail-->
|
||||
<FontAwesomeIcon v-if="isFile" class="file-icon" icon="file"/>
|
||||
|
||||
<!--Image thumbnail-->
|
||||
<img v-if="isImage" :src="data.thumbnail" :alt="data.name"/>
|
||||
<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"
|
||||
/>
|
||||
<FontAwesomeIcon v-if="isFolder" :class="{'is-deleted': isDeleted}" class="folder-icon" icon="folder"/>
|
||||
</div>
|
||||
|
||||
<!--Name-->
|
||||
<div class="item-name">
|
||||
<!--Name-->
|
||||
<span
|
||||
<b
|
||||
ref="name"
|
||||
@input="changeItemName"
|
||||
:contenteditable="!$isMobile() && !$isTrashLocation()"
|
||||
@input="renameItem"
|
||||
:contenteditable="canEditName"
|
||||
class="name"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
{{ itemName }}
|
||||
</b>
|
||||
|
||||
<!--Other attributes-->
|
||||
<span v-if="isFile || isImage" class="item-size">{{ data.filesize }}, {{ timeStamp }}</span>
|
||||
<div class="item-info">
|
||||
|
||||
<span v-if="isFolder" class="item-length">
|
||||
{{ folderItems == 0 ? 'Empty' : (folderItems + ' Item') | pluralize(folderItems) }}, {{ timeStamp }}
|
||||
</span>
|
||||
<!--Shared Icon-->
|
||||
<div v-if="$checkPermission('master') && data.shared" class="item-shared">
|
||||
<FontAwesomeIcon class="shared-icon" icon="share"/>
|
||||
</div>
|
||||
|
||||
<!--Participant owner Icon-->
|
||||
<div v-if="$checkPermission('master') && data.user_scope !== 'master'" class="item-shared">
|
||||
<FontAwesomeIcon class="shared-icon" icon="user-edit"/>
|
||||
</div>
|
||||
|
||||
<!--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>
|
||||
|
||||
<!--Go Next icon-->
|
||||
<div class="actions" v-if="$isMobile()">
|
||||
<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>
|
||||
@@ -74,21 +85,30 @@
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'FileItem',
|
||||
name: 'FileItemList',
|
||||
props: ['data'],
|
||||
computed: {
|
||||
...mapGetters(['preview_type']),
|
||||
...mapGetters(['FilePreviewType']),
|
||||
isFolder() {
|
||||
return this.data.type === 'folder'
|
||||
},
|
||||
isFile() {
|
||||
return this.data.type === 'file'
|
||||
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 ? 'Deleted ' + this.data.deleted_at : this.data.created_at
|
||||
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
|
||||
@@ -98,9 +118,6 @@
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
pluralize(word, amount) {
|
||||
return amount > 1 ? word + 's' : word
|
||||
},
|
||||
limitCharacters(str) {
|
||||
|
||||
if (str.length > 3) {
|
||||
@@ -115,13 +132,13 @@
|
||||
return {
|
||||
isClicked: false,
|
||||
area: false,
|
||||
item: undefined,
|
||||
itemName: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showItemActions() {
|
||||
// Load file info detail
|
||||
this.$store.dispatch('loadFileInfoDetail', this.data)
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
|
||||
|
||||
//this.isClicked = true
|
||||
|
||||
@@ -137,25 +154,29 @@
|
||||
},
|
||||
clickedItem(e) {
|
||||
events.$emit('contextMenu:hide')
|
||||
events.$emit('fileItem:deselect')
|
||||
|
||||
// Set clicked item
|
||||
this.isClicked = true
|
||||
|
||||
// Open in mobile version on first click
|
||||
if (this.$isMobile() && this.isFolder) {
|
||||
|
||||
// Go to folder
|
||||
this.$store.dispatch('goToFolder', [this.data, false])
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [this.data, false])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.data, false])
|
||||
}
|
||||
}
|
||||
|
||||
// Load file info detail
|
||||
this.$store.dispatch('loadFileInfoDetail', this.data)
|
||||
this.$store.commit('GET_FILEINFO_DETAIL', this.data)
|
||||
|
||||
// Get target classname
|
||||
let itemClass = e.target.className
|
||||
|
||||
if (
|
||||
['name', 'icon', 'file-link', 'file-icon-text'].includes(
|
||||
itemClass
|
||||
)
|
||||
)
|
||||
if (['name', 'icon', 'file-link', 'file-icon-text'].includes(itemClass))
|
||||
return
|
||||
},
|
||||
goToItem() {
|
||||
@@ -171,15 +192,20 @@
|
||||
}
|
||||
|
||||
if (this.isFolder) {
|
||||
// Go to folder
|
||||
this.$store.dispatch('goToFolder', [this.data, false])
|
||||
|
||||
if (this.$isThisLocation('public')) {
|
||||
this.$store.dispatch('browseShared', [this.data, false])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.data, false])
|
||||
}
|
||||
}
|
||||
},
|
||||
changeItemName: debounce(function (e) {
|
||||
// Prevent submit empty string
|
||||
if (e.target.innerText === '') return
|
||||
renameItem: debounce(function (e) {
|
||||
|
||||
this.$store.dispatch('changeItemName', {
|
||||
// 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
|
||||
@@ -187,20 +213,17 @@
|
||||
}, 300)
|
||||
},
|
||||
created() {
|
||||
this.item = this.data
|
||||
|
||||
events.$on('fileItem:clicked', unique_id => {
|
||||
if (this.data.unique_id == unique_id) {
|
||||
this.isClicked = true
|
||||
} else {
|
||||
this.isClicked = false
|
||||
}
|
||||
})
|
||||
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
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -240,17 +263,43 @@
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
.item-info {
|
||||
display: block;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.item-shared {
|
||||
display: inline-block;
|
||||
|
||||
.label {
|
||||
@include font-size(12);
|
||||
font-weight: 400;
|
||||
color: $theme;
|
||||
}
|
||||
|
||||
.shared-icon {
|
||||
@include font-size(9);
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-size,
|
||||
.item-length {
|
||||
@include font-size(12);
|
||||
font-weight: 100;
|
||||
font-weight: 400;
|
||||
color: $text-muted;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.name {
|
||||
white-space: nowrap;
|
||||
//display: inline-block;
|
||||
|
||||
&[contenteditable] {
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
&[contenteditable='true']:hover {
|
||||
text-decoration: underline;
|
||||
@@ -259,7 +308,7 @@
|
||||
|
||||
.name {
|
||||
color: $text;
|
||||
@include font-size(15);
|
||||
@include font-size(14);
|
||||
font-weight: 700;
|
||||
max-height: 40px;
|
||||
overflow: hidden;
|
||||
@@ -278,6 +327,7 @@
|
||||
}
|
||||
|
||||
.icon-item {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
flex: 0 0 50px;
|
||||
line-height: 0;
|
||||
@@ -307,38 +357,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.file {
|
||||
.file-icon-text {
|
||||
line-height: 1;
|
||||
top: 40%;
|
||||
@include font-size(11);
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
|
||||
.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;
|
||||
}
|
||||
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 {
|
||||
img {
|
||||
object-fit: cover;
|
||||
user-select: none;
|
||||
max-width: 100%;
|
||||
border-radius: 5px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.image {
|
||||
object-fit: cover;
|
||||
user-select: none;
|
||||
max-width: 100%;
|
||||
border-radius: 5px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
60
resources/js/components/FilesView/FilePreview.vue
Normal file
60
resources/js/components/FilesView/FilePreview.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div v-if="canBePreview" class="preview">
|
||||
<img v-if="fileInfoDetail.type == 'image'" :src="fileInfoDetail.thumbnail" :alt="fileInfoDetail.name" />
|
||||
<audio v-else-if="fileInfoDetail.type == 'audio'" :src="fileInfoDetail.file_url" controlsList="nodownload" controls></audio>
|
||||
<video v-else-if="fileInfoDetail.type == 'video'" controlsList="nodownload" disablePictureInPicture playsinline controls>
|
||||
<source :src="fileInfoDetail.file_url" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { includes } from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'FilePreview',
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail']),
|
||||
canBePreview() {
|
||||
return this.fileInfoDetail && ! includes([
|
||||
'folder', 'file'
|
||||
], this.fileInfoDetail.type)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-bottom: 7px;
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
audio {
|
||||
width: 100%;
|
||||
&::-webkit-media-controls-panel {
|
||||
background-color: $light_background;
|
||||
}
|
||||
|
||||
&::-webkit-media-controls-play-button {
|
||||
color: $theme;
|
||||
}
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<button class="mobile-action-button">
|
||||
<FontAwesomeIcon class="icon" :icon="icon"></FontAwesomeIcon>
|
||||
<span class="label">{{ text }}</span>
|
||||
<span class="label">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -9,7 +11,7 @@
|
||||
export default {
|
||||
name: 'MobileActionButton',
|
||||
props: [
|
||||
'icon', 'text'
|
||||
'icon'
|
||||
],
|
||||
}
|
||||
</script>
|
||||
@@ -2,7 +2,7 @@
|
||||
<button class="mobile-action-button">
|
||||
<FontAwesomeIcon class="icon" :icon="icon"></FontAwesomeIcon>
|
||||
<label label="file" class="label button file-input button-base">
|
||||
{{ text }}
|
||||
<slot></slot>
|
||||
<input
|
||||
accept="*"
|
||||
v-show="false"
|
||||
@@ -20,7 +20,7 @@
|
||||
export default {
|
||||
name: 'MobileActionButtonUpload',
|
||||
props: [
|
||||
'icon', 'text'
|
||||
'icon'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
106
resources/js/components/FilesView/MobileActions.vue
Normal file
106
resources/js/components/FilesView/MobileActions.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div id="mobile-actions-wrapper" v-if="$isMinimalScale()">
|
||||
|
||||
<!--Actions for trash location with MASTER permission--->
|
||||
<div v-if="$isThisLocation(['trash', 'trash-root']) && $checkPermission('master')" class="mobile-actions">
|
||||
<MobileActionButton @click.native="switchPreview" :icon="previewIcon">
|
||||
{{ previewText }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButton @click.native="$store.dispatch('emptyTrash')" icon="trash-alt">
|
||||
{{ $t('context_menu.empty_trash') }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--ContextMenu for Base location with MASTER permission-->
|
||||
<div v-if="$isThisLocation(['base', 'shared', 'public']) && $checkPermission(['master', 'editor'])" class="mobile-actions">
|
||||
<MobileActionButton @click.native="createFolder" icon="folder-plus">
|
||||
{{ $t('context_menu.add_folder') }}
|
||||
</MobileActionButton>
|
||||
<MobileActionButtonUpload @input.native="$uploadFiles" icon="upload">
|
||||
{{ $t('context_menu.upload') }}
|
||||
</MobileActionButtonUpload>
|
||||
<MobileActionButton @click.native="switchPreview" :icon="previewIcon">
|
||||
{{ previewText }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--ContextMenu for Base location with VISITOR permission-->
|
||||
<div v-if="$isThisLocation(['base', 'shared', 'public']) && $checkPermission('visitor')" class="mobile-actions">
|
||||
<MobileActionButton @click.native="switchPreview" :icon="previewIcon">
|
||||
{{ previewText }}
|
||||
</MobileActionButton>
|
||||
</div>
|
||||
|
||||
<!--Upload Progressbar-->
|
||||
<UploadProgress />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MobileActionButtonUpload from '@/components/FilesView/MobileActionButtonUpload'
|
||||
import MobileActionButton from '@/components/FilesView/MobileActionButton'
|
||||
import UploadProgress from '@/components/FilesView/UploadProgress'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {debounce} from 'lodash'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'MobileActions',
|
||||
components: {
|
||||
MobileActionButtonUpload,
|
||||
MobileActionButton,
|
||||
UploadProgress,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['FilePreviewType']),
|
||||
previewIcon() {
|
||||
return this.FilePreviewType === 'list' ? 'th' : 'th-list'
|
||||
},
|
||||
previewText() {
|
||||
return this.FilePreviewType === 'list' ? this.$t('preview_type.grid') : this.$t('preview_type.list')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
switchPreview() {
|
||||
this.$store.dispatch('changePreviewType')
|
||||
},
|
||||
createFolder() {
|
||||
if (this.$isMobile()) {
|
||||
// Get folder name
|
||||
let folderName = prompt(this.$t('popup_create_folder.title'))
|
||||
|
||||
// Create folder
|
||||
if (folderName) this.$createFolder(folderName)
|
||||
} else {
|
||||
// Create folder
|
||||
this.$createFolder(this.$t('popup_create_folder.folder_default_name'))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
|
||||
#mobile-actions-wrapper {
|
||||
background: white;
|
||||
position: sticky;
|
||||
top: 35px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.mobile-actions {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
white-space: nowrap;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#mobile-actions-wrapper {
|
||||
background: $dark_mode_background;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
293
resources/js/components/FilesView/MobileMenu.vue
Normal file
293
resources/js/components/FilesView/MobileMenu.vue
Normal file
@@ -0,0 +1,293 @@
|
||||
<template>
|
||||
<div class="options-wrapper">
|
||||
<transition name="context-menu">
|
||||
<div
|
||||
v-if="isVisible"
|
||||
ref="contextmenu"
|
||||
class="options"
|
||||
@click="closeAndResetContextMenu"
|
||||
>
|
||||
<div class="menu-wrapper">
|
||||
|
||||
<!--Mobile for trash location-->
|
||||
<ul v-if="$isThisLocation(['trash', 'trash-root']) && $checkPermission('master')" class="menu-options">
|
||||
<li class="menu-option" @click="$store.dispatch('restoreItem', fileInfoDetail)" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.restore') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
<li class="menu-option delete" @click="deleteItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--Mobile for Base location-->
|
||||
<ul v-if="$isThisLocation(['shared']) && $checkPermission('master')" class="menu-options">
|
||||
<li class="menu-option" @click="addToFavourites" v-if="fileInfoDetail && isFolder">
|
||||
{{ isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="renameItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="shareItem" v-if="fileInfoDetail">
|
||||
{{ fileInfoDetail.shared ? $t('context_menu.share_edit') : $t('context_menu.share') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
<li class="menu-option delete" @click="deleteItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--Mobile for Base location-->
|
||||
<ul v-if="$isThisLocation(['base']) && $checkPermission('master')" class="menu-options">
|
||||
<li class="menu-option" @click="addToFavourites" v-if="fileInfoDetail && isFolder">
|
||||
{{ isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="renameItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.move') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="shareItem" v-if="fileInfoDetail">
|
||||
{{ fileInfoDetail.shared ? $t('context_menu.share_edit') : $t('context_menu.share') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
<li class="menu-option delete" @click="deleteItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.delete') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--Mobile for Base location with EDITOR permission-->
|
||||
<ul v-if="$isThisLocation(['base', 'public']) && $checkPermission('editor')" class="menu-options">
|
||||
<li class="menu-option" @click="renameItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.rename') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="moveItem" v-if="fileInfoDetail">
|
||||
{{ $t('context_menu.move') }}
|
||||
</li>
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--Mobile for Base location with VISITOR permission-->
|
||||
<ul v-if="$isThisLocation(['base', 'public']) && $checkPermission('visitor')" class="menu-options">
|
||||
<li class="menu-option" @click="downloadItem" v-if="! isFolder">
|
||||
{{ $t('context_menu.download') }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="fade">
|
||||
<div v-show="isVisible" class="vignette" @click="closeAndResetContextMenu"></div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {events} from '@/bus'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'MobileMenu',
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'app']),
|
||||
isInFavourites() {
|
||||
return this.app.favourites.find(el => el.unique_id == this.fileInfoDetail.unique_id)
|
||||
},
|
||||
isFile() {
|
||||
return (this.fileInfoDetail && this.fileInfoDetail.type !== 'folder') && (this.fileInfoDetail && this.fileInfoDetail.type !== 'image')
|
||||
},
|
||||
isImage() {
|
||||
return this.fileInfoDetail && this.fileInfoDetail.type === 'image'
|
||||
},
|
||||
isFolder() {
|
||||
return this.fileInfoDetail && this.fileInfoDetail.type === 'folder'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
moveItem() {
|
||||
// Open move item popup
|
||||
events.$emit('popup:open', {name: 'move', item: this.fileInfoDetail})
|
||||
},
|
||||
shareItem() {
|
||||
if (this.fileInfoDetail.shared) {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {name: 'share-edit', item: this.fileInfoDetail})
|
||||
} else {
|
||||
// Open share item popup
|
||||
events.$emit('popup:open', {name: 'share-create', item: this.fileInfoDetail})
|
||||
}
|
||||
},
|
||||
addToFavourites() {
|
||||
if (this.app.favourites && !this.app.favourites.find(el => el.unique_id == this.fileInfoDetail.unique_id)) {
|
||||
this.$store.dispatch('addToFavourites', this.fileInfoDetail)
|
||||
} else {
|
||||
this.$store.dispatch('removeFromFavourites', this.fileInfoDetail)
|
||||
}
|
||||
},
|
||||
downloadItem() {
|
||||
// Download file
|
||||
this.$downloadFile(
|
||||
this.fileInfoDetail.file_url,
|
||||
this.fileInfoDetail.name + '.' + this.fileInfoDetail.mimetype
|
||||
)
|
||||
},
|
||||
deleteItem() {
|
||||
// Dispatch remove item
|
||||
this.$store.dispatch('deleteItem', this.fileInfoDetail)
|
||||
},
|
||||
renameItem() {
|
||||
let itemName = prompt(
|
||||
this.$t('popup_rename.title'),
|
||||
this.fileInfoDetail.name
|
||||
)
|
||||
|
||||
if (itemName && itemName !== '') {
|
||||
|
||||
let item = {
|
||||
unique_id: this.fileInfoDetail.unique_id,
|
||||
type: this.fileInfoDetail.type,
|
||||
name: itemName
|
||||
}
|
||||
|
||||
this.$store.dispatch('renameItem', item)
|
||||
|
||||
// Change item name if is mobile device or prompted
|
||||
if (this.$isMobile()) {
|
||||
events.$emit('change:name', item)
|
||||
}
|
||||
}
|
||||
},
|
||||
closeAndResetContextMenu() {
|
||||
events.$emit('fileItem:deselect')
|
||||
|
||||
// Close context menu
|
||||
this.isVisible = false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
// Show context menu
|
||||
events.$on('mobileMenu:show', () => {
|
||||
this.isVisible = !this.isVisible
|
||||
})
|
||||
|
||||
// Hide mobile menu
|
||||
events.$on('mobileMenu:hide', () => {
|
||||
this.isVisible = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.vignette {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 9;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
overflow: hidden;
|
||||
|
||||
&.showed {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu-options {
|
||||
margin-top: 10px;
|
||||
box-shadow: $shadow;
|
||||
background: white;
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
|
||||
.menu-option {
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.15px;
|
||||
@include font-size(15);
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
padding: 20px 10px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid $light_mode_border;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.vignette {
|
||||
background: $dark_mode_vignette;
|
||||
}
|
||||
|
||||
.options {
|
||||
|
||||
.menu-options {
|
||||
background: $dark_mode_background;
|
||||
|
||||
.menu-option {
|
||||
border-color: $dark_mode_border_color;
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Transition
|
||||
.context-menu-enter-active,
|
||||
.fade-enter-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.context-menu-leave-active,
|
||||
.fade-leave-active {
|
||||
transition: all 200ms;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.context-menu-enter,
|
||||
.context-menu-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.context-menu-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="mobile-toolbar">
|
||||
<div class="mobile-toolbar" v-if="$isMinimalScale()">
|
||||
|
||||
<!-- Go back-->
|
||||
<div @click="goBack" class="go-back-button">
|
||||
@@ -14,8 +14,8 @@
|
||||
<div class="directory-name">{{ directoryName }}</div>
|
||||
|
||||
<!--More Actions-->
|
||||
<div class="more-actions-button" @click="showSidebarMenu">
|
||||
<div class="tap-area">
|
||||
<div class="more-actions-button">
|
||||
<div class="tap-area" @click="showSidebarMenu" v-if="$checkPermission('master')">
|
||||
<FontAwesomeIcon icon="bars" v-if="isSmallAppSize"></FontAwesomeIcon>
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,9 +23,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ToolbarButtonUpload from '@/components/VueFileManagerComponents/FilesView/ToolbarButtonUpload'
|
||||
import ToolbarButton from '@/components/VueFileManagerComponents/FilesView/ToolbarButton'
|
||||
import SearchBar from '@/components/VueFileManagerComponents/FilesView/SearchBar'
|
||||
import ToolbarButtonUpload from '@/components/FilesView/ToolbarButtonUpload'
|
||||
import ToolbarButton from '@/components/FilesView/ToolbarButton'
|
||||
import SearchBar from '@/components/FilesView/SearchBar'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'fileInfoVisible',
|
||||
'FilePreviewType',
|
||||
'fileInfoDetail',
|
||||
'currentFolder',
|
||||
'browseHistory',
|
||||
'homeDirectory',
|
||||
'preview_type',
|
||||
'appSize',
|
||||
]),
|
||||
directoryName() {
|
||||
@@ -75,7 +75,11 @@
|
||||
this.$store.commit('FLUSH_BROWSER_HISTORY')
|
||||
|
||||
} else {
|
||||
this.$store.dispatch('goToFolder', [this.previousFolder, true])
|
||||
if ( this.$isThisLocation('public') ) {
|
||||
this.$store.dispatch('browseShared', [this.previousFolder, true])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.previousFolder, true])
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -130,9 +134,9 @@
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
vertical-align: middle;
|
||||
@include font-size(17);
|
||||
@include font-size(16);
|
||||
color: $text;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
max-width: 220px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -40,7 +40,7 @@ export default {
|
||||
@media only screen and (min-width: 680px) and (prefers-color-scheme: dark) {
|
||||
|
||||
.progress-bar {
|
||||
background: $dark_mode_background;
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -5,7 +5,7 @@
|
||||
class="query"
|
||||
type="text"
|
||||
name="query"
|
||||
placeholder="Search files…"
|
||||
:placeholder="$t('inputs.placeholder_search_files')"
|
||||
/>
|
||||
<div class="icon" v-if="!isQuery">
|
||||
<FontAwesomeIcon icon="search"></FontAwesomeIcon>
|
||||
@@ -49,11 +49,13 @@
|
||||
this.$store.dispatch('getSearchResult', value)
|
||||
} else if (typeof value !== 'undefined') {
|
||||
if (this.currentFolder) {
|
||||
|
||||
// Get back after delete query to previosly folder
|
||||
this.$store.dispatch('goToFolder', [
|
||||
this.currentFolder,
|
||||
true
|
||||
])
|
||||
if ( this.$isThisLocation('public') ) {
|
||||
this.$store.dispatch('browseShared', [this.currentFolder, true])
|
||||
} else {
|
||||
this.$store.dispatch('getFolder', [this.currentFolder, true])
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.commit('CHANGE_SEARCHING_STATE', false)
|
||||
@@ -88,6 +90,7 @@
|
||||
&::placeholder {
|
||||
color: $text;
|
||||
@include font-size(14);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
45
resources/js/components/FilesView/Spinner.vue
Normal file
45
resources/js/components/FilesView/Spinner.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div id="loading-bar-spinner" class="spinner">
|
||||
<div class="spinner-icon"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Spinner'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
#loading-bar-spinner.spinner {
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
top: 50%;
|
||||
margin-top: -20px;
|
||||
position: absolute;
|
||||
z-index: 19 !important;
|
||||
animation: loading-bar-spinner 400ms linear infinite;
|
||||
}
|
||||
|
||||
#loading-bar-spinner.spinner .spinner-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: solid 4px transparent;
|
||||
border-top-color: $theme !important;
|
||||
border-left-color: $theme !important;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@keyframes loading-bar-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -8,7 +8,7 @@
|
||||
type="file"
|
||||
name="files[]"
|
||||
multiple
|
||||
:disabled="$isTrashLocation() ? true : false"
|
||||
:disabled="$isThisLocation(['trash', 'trash-root'])"
|
||||
/>
|
||||
</label>
|
||||
</template>
|
||||
@@ -2,11 +2,7 @@
|
||||
<transition name="info-panel">
|
||||
<div v-if="uploadingFilesCount" class="upload-progress">
|
||||
<div class="progress-title">
|
||||
<span
|
||||
>Uploading files {{ uploadingFilesCount.current }}/{{
|
||||
uploadingFilesCount.total
|
||||
}}</span
|
||||
>
|
||||
<span>{{ $t('uploading.progress', {current:uploadingFilesCount.current, total: uploadingFilesCount.total}) }}</span>
|
||||
</div>
|
||||
<ProgressBar :progress="uploadingFileProgress"/>
|
||||
</div>
|
||||
@@ -14,7 +10,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProgressBar from '@/components/VueFileManagerComponents/FilesView/ProgressBar'
|
||||
import ProgressBar from '@/components/FilesView/ProgressBar'
|
||||
import {mapGetters} from 'vuex'
|
||||
|
||||
export default {
|
||||
44
resources/js/components/Others/ActionButton.vue
Normal file
44
resources/js/components/Others/ActionButton.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="action-button">
|
||||
<FontAwesomeIcon class="icon" :icon="icon" />
|
||||
<span class="label">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ActionButton',
|
||||
props: ['icon'],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.action-button {
|
||||
cursor: pointer;
|
||||
|
||||
.label {
|
||||
@include font-size(12);
|
||||
color: $theme;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@include font-size(10);
|
||||
display: inline-block;
|
||||
margin-right: 2px;
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
</style>
|
||||
90
resources/js/components/Others/Forms/CopyInput.vue
Normal file
90
resources/js/components/Others/Forms/CopyInput.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="inline-wrapper icon-append copy-input" :class="size" @click="copyUrl">
|
||||
<input ref="sel" :value="value" id="link-input" type="text" class="input-text" readonly>
|
||||
<div class="icon">
|
||||
<FontAwesomeIcon :icon="isCopiedLink ? 'check' : 'link'"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'CopyInput',
|
||||
props: ['size', 'value'],
|
||||
data() {
|
||||
return {
|
||||
isCopiedLink: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
copyUrl() {
|
||||
|
||||
// Get input value
|
||||
var copyText = document.getElementById("link-input");
|
||||
|
||||
// select link
|
||||
copyText.select();
|
||||
copyText.setSelectionRange(0, 99999);
|
||||
|
||||
// Copy
|
||||
document.execCommand("copy");
|
||||
|
||||
// Mark button as copied
|
||||
this.isCopiedLink = true
|
||||
|
||||
// Reset copy button
|
||||
setTimeout(() => {this.isCopiedLink = false}, 1000)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@assets/app.scss";
|
||||
@import "@assets/vue-file-manager/_inapp-forms.scss";
|
||||
|
||||
// Single page
|
||||
.copy-input {
|
||||
|
||||
&.small {
|
||||
|
||||
&.icon-append {
|
||||
|
||||
.icon {
|
||||
padding: 8px 10px;
|
||||
@include font-size(11);
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 6px 10px;
|
||||
@include font-size(13);
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:disabled {
|
||||
color: $text;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.copy-input {
|
||||
input {
|
||||
color: $dark_mode_text_primary;
|
||||
|
||||
&:disabled {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
194
resources/js/components/Others/Forms/SelectInput.vue
Normal file
194
resources/js/components/Others/Forms/SelectInput.vue
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="select">
|
||||
|
||||
<!--Area-->
|
||||
<div class="input-area" :class="{'is-active': isOpen, 'is-error': isError}" @click="openMenu">
|
||||
|
||||
<!--If is selected-->
|
||||
<div class="selected" v-if="selected">
|
||||
<div class="option-icon" v-if="selected.icon">
|
||||
<FontAwesomeIcon :icon="selected.icon" />
|
||||
</div>
|
||||
<span class="option-value">{{ selected.label }}</span>
|
||||
</div>
|
||||
|
||||
<!--If is empty-->
|
||||
<div class="not-selected" v-if="! selected">
|
||||
<span class="option-value placehoder">{{ placeholder }}</span>
|
||||
</div>
|
||||
|
||||
<FontAwesomeIcon icon="chevron-down" class="chevron"/>
|
||||
</div>
|
||||
|
||||
<!--Options-->
|
||||
<transition name="slide-in">
|
||||
<ul class="input-options" v-if="isOpen">
|
||||
<li class="option-item" @click="selectOption(option)" v-for="(option, i) in options" :key="i">
|
||||
<div class="option-icon" v-if="option.icon">
|
||||
<FontAwesomeIcon :icon="option.icon" />
|
||||
</div>
|
||||
<span class="option-value">{{ option.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:'SelectInput',
|
||||
props: ['options', 'isError', 'default', 'placeholder'],
|
||||
data() {
|
||||
return {
|
||||
selected: undefined,
|
||||
isOpen: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectOption(option) {
|
||||
|
||||
// Emit selected
|
||||
this.$emit('input', option.value)
|
||||
|
||||
// Get selected
|
||||
this.selected = option
|
||||
|
||||
// Close menu
|
||||
this.isOpen = false
|
||||
},
|
||||
openMenu() {
|
||||
this.isOpen = ! this.isOpen
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
||||
if (this.default)
|
||||
this.selected = this.options.find(option => option.value === this.default)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.select {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.input-options {
|
||||
background: $light_background;
|
||||
border-radius: 8px;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
top: 65px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
|
||||
.option-item {
|
||||
padding: 13px 20px;
|
||||
display: block;
|
||||
border-bottom: 1px solid #EBEBEB;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme;
|
||||
background: rgba($theme, .1);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-area {
|
||||
justify-content: space-between;
|
||||
background: $light_background;
|
||||
border: 1px solid transparent;
|
||||
@include transition(150ms);
|
||||
align-items: center;
|
||||
border-radius: 8px;
|
||||
padding: 13px 20px;
|
||||
display: flex;
|
||||
outline: 0;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
.chevron {
|
||||
@include transition(150ms);
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
border-color: $theme;
|
||||
box-shadow: 0 0 7px rgba($theme, 0.3);
|
||||
|
||||
.chevron {
|
||||
@include transform(rotate(180deg));
|
||||
}
|
||||
}
|
||||
|
||||
&.is-error {
|
||||
border-color: $danger;
|
||||
box-shadow: 0 0 7px rgba($danger, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.option-icon {
|
||||
width: 20px;
|
||||
display: inline-block;
|
||||
@include font-size(12);
|
||||
}
|
||||
|
||||
.option-value {
|
||||
@include font-size(15);
|
||||
font-weight: 700;
|
||||
width: 100%;
|
||||
|
||||
&.placehoder {
|
||||
color: $light_text;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-in-enter-active {
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
.slide-in-enter /* .list-leave-active below version 2.1.8 */
|
||||
{
|
||||
opacity: 0;
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
.input-area {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
.option-icon {
|
||||
path {
|
||||
fill: $theme
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-options {
|
||||
background: $dark_mode_foreground;
|
||||
|
||||
.option-item {
|
||||
border-bottom: none;
|
||||
|
||||
&:hover {
|
||||
color: $theme;
|
||||
background: rgba($theme, .1);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
98
resources/js/components/Others/Forms/SwitchInput.vue
Normal file
98
resources/js/components/Others/Forms/SwitchInput.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class="input-wrapper">
|
||||
<div class="switch-content">
|
||||
<label class="input-label" v-if="label">{{ label }}:</label>
|
||||
<small class="input-info" v-if="info">{{ info }}</small>
|
||||
</div>
|
||||
|
||||
<div class="switch-content text-right">
|
||||
<div
|
||||
class="switch"
|
||||
:class="{ active: isSwitched }"
|
||||
@click="changeState"
|
||||
>
|
||||
<div class="switch-button"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:'SwitchInput',
|
||||
props: ['label', 'name', 'state', 'info'],
|
||||
data() {
|
||||
return {
|
||||
isSwitched: undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeState() {
|
||||
this.isSwitched = ! this.isSwitched
|
||||
this.$emit('input', this.isSwitched)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isSwitched = this.state
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.input-wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.input-label {
|
||||
color: $text;
|
||||
}
|
||||
|
||||
.switch-content {
|
||||
width: 100%;
|
||||
|
||||
&:last-child {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.switch {
|
||||
width: 50px;
|
||||
height: 28px;
|
||||
border-radius: 50px;
|
||||
display: block;
|
||||
background: #f1f1f5;
|
||||
position: relative;
|
||||
@include transition;
|
||||
|
||||
.switch-button {
|
||||
@include transition;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50px;
|
||||
display: block;
|
||||
background: white;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
box-shadow: 0 2px 4px rgba(37, 38, 94, 0.1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: $theme;
|
||||
|
||||
.switch-button {
|
||||
left: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.switch {
|
||||
background: $dark_mode_foreground;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
132
resources/js/components/Others/MoveItem.vue
Normal file
132
resources/js/components/Others/MoveItem.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<PopupWrapper name="move">
|
||||
<!--Title-->
|
||||
<PopupHeader :title="$t('popup_move_item.title')" />
|
||||
|
||||
<!--Content-->
|
||||
<PopupContent type="height-limited" v-if="pickedItem">
|
||||
|
||||
<!--Show Spinner when loading folders-->
|
||||
<Spinner v-if="isLoadingTree"/>
|
||||
|
||||
<!--Folder tree-->
|
||||
<div v-if="! isLoadingTree && navigation">
|
||||
<ThumbnailItem class="item-thumbnail" :item="pickedItem" info="location"/>
|
||||
<TreeMenu :depth="1" :nodes="items" v-for="items in navigation" :key="items.unique_id"/>
|
||||
</div>
|
||||
</PopupContent>
|
||||
|
||||
<!--Actions-->
|
||||
<PopupActions>
|
||||
<ButtonBase
|
||||
class="popup-button"
|
||||
@click.native="$closePopup()"
|
||||
button-style="secondary"
|
||||
>{{ $t('popup_move_item.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
class="popup-button"
|
||||
@click.native="moveItem"
|
||||
:button-style="selectedFolder ? 'theme' : 'secondary'"
|
||||
>{{ $t('popup_move_item.submit') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
</PopupWrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PopupWrapper from '@/components/Others/Popup/PopupWrapper'
|
||||
import PopupActions from '@/components/Others/Popup/PopupActions'
|
||||
import PopupContent from '@/components/Others/Popup/PopupContent'
|
||||
import PopupHeader from '@/components/Others/Popup/PopupHeader'
|
||||
import ThumbnailItem from '@/components/Others/ThumbnailItem'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import TreeMenu from '@/components/Others/TreeMenu'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
|
||||
export default {
|
||||
name: 'MoveItem',
|
||||
components: {
|
||||
ThumbnailItem,
|
||||
PopupWrapper,
|
||||
PopupActions,
|
||||
PopupContent,
|
||||
PopupHeader,
|
||||
ButtonBase,
|
||||
TreeMenu,
|
||||
Spinner,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['navigation']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedFolder: undefined,
|
||||
pickedItem: undefined,
|
||||
isLoadingTree: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
moveItem() {
|
||||
|
||||
// Prevent empty submit
|
||||
if (! this.selectedFolder) return
|
||||
|
||||
// Move item
|
||||
this.$store.dispatch('moveItem', [this.pickedItem, this.selectedFolder])
|
||||
|
||||
// Close popup
|
||||
events.$emit('popup:close')
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
// Select folder in tree
|
||||
events.$on('pick-folder', folder => {
|
||||
|
||||
if (folder.unique_id === this.pickedItem.unique_id) {
|
||||
this.selectedFolder = undefined
|
||||
} else {
|
||||
this.selectedFolder = folder
|
||||
}
|
||||
})
|
||||
|
||||
// Show Move item popup
|
||||
events.$on('popup:open', args => {
|
||||
|
||||
if (args.name !== 'move') return
|
||||
|
||||
// Show tree spinner
|
||||
this.isLoadingTree = true
|
||||
|
||||
// Get folder tree and hide spinner
|
||||
this.$store.dispatch('getFolderTree').then(() => {
|
||||
this.isLoadingTree = false
|
||||
})
|
||||
|
||||
// Store picked item
|
||||
this.pickedItem = args.item
|
||||
})
|
||||
|
||||
// Close popup
|
||||
events.$on('popup:close', () => {
|
||||
|
||||
// Clear selected folder
|
||||
setTimeout(() => {
|
||||
this.selectedFolder = undefined
|
||||
}, 150)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@assets/app.scss";
|
||||
|
||||
.item-thumbnail {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -26,7 +26,10 @@
|
||||
},
|
||||
methods: {
|
||||
goHome() {
|
||||
if (this.isSmallAppSize) events.$emit('show:sidebar')
|
||||
if (this.isSmallAppSize) {
|
||||
events.$emit('show:sidebar')
|
||||
this.$router.push({name: 'Files'})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user