Compare commits

..

14 Commits
v1.1 ... v1.3.1

Author SHA1 Message Date
carodej
9db34fd90e file delete bugfixes 2020-04-08 09:37:54 +02:00
carodej
01b399e4a6 fixed - Cannot read property '$t' 2020-04-06 19:56:56 +02:00
carodej
6235ffd0dc deleted file 2020-04-05 12:19:21 +02:00
MakingCG
4504276563 Version 1.3
- i18n localization support
- Added SK, EN language files
- Video/Audio preview in file preview panel (Thanks to Joshua Fouyon to participating on this feature)
- Drop uploading (You can now drag files from desktop and drop it to VueFileManager)
- Fixed bug when rename item in safari browser
- Fixed bug when you drag folder from trash to favourites in sidebar panel
- small functions and design improvements
2020-04-03 11:52:54 +02:00
MakingCG
96da39923d Update app.php 2020-04-01 18:47:37 +02:00
MakingCG
8633650f82 Added i18n support 2020-04-01 18:44:47 +02:00
MakingCG
182091c21a bugfixes 2020-03-29 11:42:32 +02:00
MakingCG
7bed9ad7b8 bug fixes 2020-03-28 19:30:04 +01:00
MakingCG
7eb4238efd bug fixes 2020-03-28 19:17:58 +01:00
MakingCG
ea74c8885f Version 1.2
- Move your items by folder tree
- Fixed bug with image rotation on iOS Device
2020-03-28 12:26:51 +01:00
MakingCG
7cdf463e4e bug fixes 2020-03-16 18:23:22 +01:00
MakingCG
850f910b96 Update Readme.md 2020-03-15 11:11:21 +01:00
MakingCG
4492696e3d readme 2020-03-15 11:09:42 +01:00
MakingCG
dc74020f2d Config update 2020-03-15 10:55:32 +01:00
83 changed files with 3587 additions and 2556 deletions

6
.idea/misc.xml generated
View File

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

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

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

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

View File

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

View File

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

@@ -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="&lt;d768a9d2-ae0a-4b11-a436-c632a530c3ce&gt;/var/www/devvuefilemanagerlaravel.hi5ve.digital/.env" />
<option value="&lt;d768a9d2-ae0a-4b11-a436-c632a530c3ce&gt;/etc/apache2/sites-available/devvuefilemanager.hi5ve.digital.conf" />
<option value="&lt;d768a9d2-ae0a-4b11-a436-c632a530c3ce&gt;/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="&lt;d768a9d2-ae0a-4b11-a436-c632a530c3ce&gt;/var/www/devvuefilemanager.hi5ve.digital/config/vuefilemanager.php" />
<option value="&lt;d768a9d2-ae0a-4b11-a436-c632a530c3ce&gt;/var/www/devvuefilemanager.hi5ve.digital/public/info.php" />
<option value="&lt;d768a9d2-ae0a-4b11-a436-c632a530c3ce&gt;/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>

BIN
.rnd Normal file

Binary file not shown.

View File

@@ -1,78 +1,50 @@
<p align="center"><img src="https://res.cloudinary.com/dtfbvvkyp/image/upload/v1566331377/laravel-logolockup-cmyk-red.svg" width="400"></p>
## VueFileManager - Make your own Private Cloud with VueFileManager client powered by Laravel and Vue
For installation, please read [Online Documentation](https://vuefilemanager.hi5ve.digital/docs/).
![VueFileManager](https://vuefilemanager.hi5ve.digital/assets/images/vue-file-manager-in-devices-dark.png)
<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>
**Features:**
## About Laravel
### Drag & Drop
Reorder your files easily, just drag your folder or file and drop to another folder.
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:
### List & Grid Preview
You can change from two types of file and folder previews. Show your items in list or grid preview.
- [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).
### Background Uploading
Your files is uploaded in the background, so nothing will stop you from working with the files.
Laravel is accessible, powerful, and provides tools required for large, robust applications.
### File & Folder searching
Search your items quickly, from anywhere in the app you are.
## Learning Laravel
### Custom Context Menu
Quick actions next to your file on your right click.
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.
### File Details
Get preview of your files quickli in right panel next to your files.
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.
### Improved Mobile User Experience
Need to quickly upload or get your files on your smartphone? Its not problem.
## Laravel Sponsors
### Laravel PHP Framework
You don't have to create your own API for VueFileManager. You can use our pre-build backend in Laravel PHP Framework.
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).
### Vue.js
Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web. We ❤️ Vue.
- **[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)
### Online Documentation
Dont worry, we will explain all things you should know to successfully start your VueFileManager instance.
## Contributing
### Night Mode
We add native support for dark mode. Now, its easy for your eyes to work with your files at night.
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
### User Login & Registration
Let user create their own account with own storage. All these accounts is protected by user login.
## Code of Conduct
### Integrated Trash
Did you delete something by accident or do you want your deleted files back? Restore your files from trash.
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).
### Navigation Sidebar
Navigate through your files easily. Add you favourites folder or look on your latest uploads.
## 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).
### Storage Limits
Set storage limits to your user account to sure, you never exceed your storage limits.

View File

@@ -9,11 +9,10 @@ use Illuminate\Support\Str;
use Laravel\Scout\Searchable;
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
use \Illuminate\Database\Eloquent\SoftDeletes;
use \Askedio\SoftCascade\Traits\SoftCascadeTrait;
class FileManagerFile extends Model
{
use Searchable, SoftDeletes, SoftCascadeTrait;
use Searchable, SoftDeletes;
protected $guarded = [
@@ -31,7 +30,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,7 +42,7 @@ 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'));
}
/**

View File

@@ -11,20 +11,15 @@ use RecursiveArrayIterator;
use RecursiveIteratorIterator;
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
use \Illuminate\Database\Eloquent\SoftDeletes;
use \Askedio\SoftCascade\Traits\SoftCascadeTrait;
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 +74,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 +86,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 +111,6 @@ class FileManagerFolder extends Model
*/
public function files()
{
return $this->hasMany('App\FileManagerFile', 'folder_id', 'unique_id');
}
@@ -178,9 +172,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) {

View File

@@ -43,7 +43,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

View File

@@ -116,8 +116,12 @@ class FileManagerController extends Controller
$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();
$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();
@@ -225,18 +229,27 @@ class FileManagerController extends Controller
// Delete folder
if ($request->type === 'folder') {
$item = FileManagerFolder::withTrashed()
->with('folders')
// Get folder
$folder = 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);
// Force delete children files
if ($request->force_delete) {
foreach ($item->files as $file) {
// Get children folder ids
$child_folders = filter_folders_ids($folder->trashed_folders, 'unique_id');
if ($request->force_delete) {
// Get children files
$files = FileManagerFile::onlyTrashed()
->where('user_id', $user->id)
->whereIn('folder_id', Arr::flatten([$request->unique_id, $child_folders]))
->get();
// Remove all children files
foreach ($files as $file) {
// Delete file
Storage::disk('local')->delete('/file-manager/' . $file->basename);
@@ -246,26 +259,22 @@ class FileManagerController extends Controller
// Delete file permanently
$file->forceDelete();
} else {
// Delete file from visibility
$file->delete();
}
}
// Delete record
if ($request->force_delete) {
// Delete folder record
$folder->forceDelete();
$item->forceDelete();
} else {
$item->delete();
// Remove folder from user favourites
$user->favourites()->detach($request->unique_id);
// Soft delete folder record
$folder->delete();
}
}
} else {
if ($request->type === 'file' || $request->type === 'image') {
$item = FileManagerFile::withTrashed()
$file = FileManagerFile::withTrashed()
->where('user_id', $user->id)
->where('unique_id', $request->unique_id)
->first();
@@ -273,17 +282,17 @@ class FileManagerController extends Controller
if ($request->force_delete) {
// Delete file
Storage::disk('local')->delete('/file-manager/' . $item->basename);
Storage::disk('local')->delete('/file-manager/' . $file->basename);
// Delete thumbnail if exist
if (!is_null($item->thumbnail)) Storage::disk('local')->delete('/file-manager/' . $item->thumbnail);
if ($file->thumbnail) Storage::disk('local')->delete('/file-manager/' . $file->getOriginal('thumbnail'));
// Delete file permanently
$item->forceDelete();
$file->forceDelete();
} else {
// Delete file from visibility
$item->delete();
// Soft delete file
$file->delete();
}
}
}
@@ -302,9 +311,21 @@ class FileManagerController extends Controller
$folders = FileManagerFolder::onlyTrashed()->where('user_id', $user_id)->get();
$files = FileManagerFile::onlyTrashed()->where('user_id', $user_id)->get();
// Force delete every item
// Force delete folder
$folders->each->forceDelete();
$files->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!', 200);
@@ -341,10 +362,7 @@ class FileManagerController extends Controller
$item->parent_id = 0;
$item->save();
}
}
// Get file
if ($request->type === 'file' || $request->type === 'image') {
} else {
// Get item
$item = FileManagerFile::onlyTrashed()->where('user_id', $user_id)->where('unique_id', $request->unique_id)->first();
@@ -360,45 +378,6 @@ class FileManagerController extends Controller
$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
*
@@ -408,8 +387,10 @@ class FileManagerController extends Controller
public function upload_item(Request $request)
{
// Check if user can upload
if (config('vuefilemanager.limit_storage_by_capacity') && user_storage_percentage() >= 100)
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(), [
@@ -426,7 +407,7 @@ class FileManagerController extends Controller
// File
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
$filetype = 'file';
$filetype = get_file_type($file);
$thumbnail = null;
$filesize = $file->getSize();
$directory = 'file-manager';
@@ -440,17 +421,16 @@ class FileManagerController extends Controller
Storage::disk('local')->putFileAs($directory, $file, $filename, 'public');
// Create image thumbnail
if (substr($file->getMimeType(), 0, 5) == 'image') {
if ($filetype == 'image') {
$filetype = 'image';
$thumbnail = 'thumbnail-' . $filename;
// Create intervention image
$image = Image::make($file->getRealPath());
$image = Image::make($file->getRealPath())->orientate();
$image->resize(256, null, function ($constraint) {
$constraint->aspectRatio();
})->save(null, 90);
})->stream();
// Store thumbnail to s3
Storage::disk('local')->put($directory . '/' . $thumbnail, $image);
@@ -560,6 +540,8 @@ class FileManagerController extends Controller
$response->header("Content-Type", $type);
$response->header("Content-Disposition", 'attachment; filename=' . $filename);
$response->header("Content-Length", $size);
$response->header("Accept-Ranges", "bytes");
$response->header("Content-Range", "bytes 0-" . $size . "/" . $size);
return $response;
}

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\FileManagerFolder;
use App\User;
use ByteUnits\Metric;
use Illuminate\Http\Request;
@@ -24,14 +25,15 @@ class UserAccountController extends Controller
$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', $user_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')),
@@ -39,6 +41,28 @@ class UserAccountController extends Controller
];
}
/**
* Get user folder tree
*
* @return array
*/
public function folder_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,
]
];
}
/**
* Update user profile
*

View File

@@ -1,6 +1,7 @@
<?php
use ByteUnits\Metric;
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\ImageManagerStatic as Image;
@@ -54,7 +55,6 @@ function check_directory($directory)
*/
function make_single_input($request)
{
// Create container
$data = [];
@@ -100,7 +100,8 @@ function get_storage_fill_percentage($used, $capacity)
*
* @return string
*/
function user_storage_percentage() {
function user_storage_percentage()
{
$user = \Illuminate\Support\Facades\Auth::user();
@@ -152,9 +153,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';
}
}

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

View File

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

View File

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

View File

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

894
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,12 @@
return [
// Your app name
'app_name' => 'VueFileManager',
// Your app logo
'app_logo' => '/assets/images/hero.svg',
// Enable or disable user account registration
'registration' => true,

View File

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

View File

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

1075
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,20 +12,21 @@
"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",
"vue": "^2.6.10",
"vue-i18n": "^8.16.0",
"vuex": "^3.0.1"
}
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

2
public/css/app.css vendored
View File

@@ -1 +1 @@
@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);

2
public/js/main.js vendored

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -6,8 +6,20 @@
<div v-if="isLogged" id="auth">
<!--System alerts-->
<Alert />
<div id="popups">
<!--System alerts-->
<Alert />
<!--Popup-->
<PopupMoveItem />
<!--Mobile Menu-->
<MobileOptionList />
<!--Background vignette-->
<Vignette />
</div>
<div id="application-wrapper">
@@ -25,19 +37,26 @@
</template>
<script>
import MobileOptionList from '@/components/VueFileManagerComponents/FilesView/MobileOptionList'
import PopupMoveItem from '@/components/VueFileManagerComponents/Others/PopupMoveItem'
import UserSettings from '@/components/VueFileManagerComponents/UserSettings'
import Vignette from '@/components/VueFileManagerComponents/Others/Vignette'
import Alert from '@/components/VueFileManagerComponents/FilesView/Alert'
import FilesView from '@/components/VueFileManagerComponents/FilesView'
import Sidebar from '@/components/VueFileManagerComponents/Sidebar'
import Auth from '@/components/VueFileManagerComponents/Auth'
import {ResizeSensor} from 'css-element-queries'
import {mapGetters} from 'vuex'
import {events} from "../bus";
export default {
name: 'VueFileManager',
components: {
MobileOptionList,
PopupMoveItem,
UserSettings,
FilesView,
Vignette,
Sidebar,
Alert,
Auth,
@@ -95,7 +114,7 @@
// Dark mode support
@media (prefers-color-scheme: dark) {
#vue-file-manager {
body, html {
background: $dark_mode_background;
color: $dark_mode_text_primary;

View File

@@ -3,24 +3,24 @@
<!--Log In by Email-->
<AuthContent name="log-in" :visible="false">
<img class="logo" src="/assets/images/hero.svg" alt="Vue File Manager logo">
<h1>Welcome Back!</h1>
<h2>Please type your email to log in:</h2>
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_login.title') }}</h1>
<h2>{{ $t('page_login.subtitle') }}</h2>
<ValidationObserver @submit.prevent="logIn" ref="log_in" v-slot="{ invalid }" tag="form"
class="form inline-form">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="loginEmail" placeholder="Type your E-mail" type="email"
<input v-model="loginEmail" :placeholder="$t('page_login.placeholder_email')" type="email"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" text="Next Step" :loading="isLoading" :disabled="isLoading"/>
<AuthButton icon="chevron-right" :text="$t('page_login.button_next')" :loading="isLoading" :disabled="isLoading"/>
</ValidationObserver>
<span v-if="config.userRegistration" class="additional-link">Dont have an account? <b
@click="goToAuthPage('sign-up')">Register account.</b></span>
<span v-if="config.userRegistration" class="additional-link">{{ $t('page_login.registration_text') }} <b
@click="goToAuthPage('sign-up')">{{ $t('page_login.registration_button') }}</b></span>
</AuthContent>
<!--Log in By Password-->
@@ -28,166 +28,166 @@
<div class="user" v-if="checkedAccount">
<img class="user-avatar" :src="checkedAccount.avatar" :alt="checkedAccount.name">
<h1>Are You {{ checkedAccount.name }}?</h1>
<h2>Confirm you by your password:</h2>
<h1>{{ $t('page_sign_in.title', {name: checkedAccount.name}) }}</h1>
<h2>{{ $t('page_sign_in.subtitle') }}</h2>
</div>
<ValidationObserver @submit.prevent="singIn" ref="sign_in" v-slot="{ invalid }" tag="form"
class="form inline-form">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="User Password" rules="required"
v-slot="{ errors }">
<input v-model="loginPassword" placeholder="Type your password" type="password"
<input v-model="loginPassword" :placeholder="$t('page_sign_in.placeholder_password')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" text="Log In" :loading="isLoading" :disabled="isLoading"/>
<AuthButton icon="chevron-right" :text="$t('page_sign_in.button_log_in')" :loading="isLoading" :disabled="isLoading"/>
</ValidationObserver>
<span class="additional-link">Forgotten your password? <b @click="goToAuthPage('forgotten-password')">Reset Password.</b></span>
<span class="additional-link">{{ $t('page_sign_in.password_reset_text') }} <b @click="goToAuthPage('forgotten-password')">{{ $t('page_sign_in.password_reset_button') }}</b></span>
</AuthContent>
<!--Forgotten your password?-->
<AuthContent name="forgotten-password" :visible="false">
<img class="logo" src="/assets/images/hero.svg" alt="Vue File Manager logo">
<h1>Forgotten Password?</h1>
<h2>Get reset link with your email:</h2>
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_forgotten_password.title') }}</h1>
<h2>{{ $t('page_forgotten_password.subtitle') }}</h2>
<ValidationObserver @submit.prevent="forgottenPassword" ref="forgotten_password" v-slot="{ invalid }"
tag="form" class="form inline-form">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="recoverEmail" placeholder="Type your E-mail" type="email"
<input v-model="recoverEmail" :placeholder="$t('page_login.placeholder_email')" type="email"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" text="Get Link" :loading="isLoading" :disabled="isLoading"/>
<AuthButton icon="chevron-right" :text="$t('page_forgotten_password.button_get_link')" :loading="isLoading" :disabled="isLoading"/>
</ValidationObserver>
<span class="additional-link">Remember your password? <b @click="goToAuthPage('log-in')">Log In.</b></span>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Create new password-->
<AuthContent name="create-new-password" :visible="false">
<img class="logo" src="/assets/images/hero.svg" alt="Vue File Manager logo">
<h1>Only One Step to Log In</h1>
<h2>Create your new password here:</h2>
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_create_password.title') }}</h1>
<h2>{{ $t('page_create_password.subtitle') }}</h2>
<ValidationObserver @submit.prevent="createNewPassword" ref="create_new_password" v-slot="{ invalid }"
tag="form" class="form block-form create-new-password">
<div class="block-wrapper">
<label>Email:</label>
<label>{{ $t('page_create_password.label_email') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="recoverPassword.email" placeholder="Type your E-mail" type="email"
<input v-model="recoverPassword.email" :placeholder="$t('page_login.placeholder_email')" type="email"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Your new password:</label>
<label>{{ $t('page_create_password.label_new_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="New Password"
rules="required" v-slot="{ errors }">
<input v-model="recoverPassword.newPassword" placeholder="Your new password" type="password"
<input v-model="recoverPassword.newPassword" :placeholder="$t('page_create_password.label_new_pass')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Confirm new password:</label>
<label>{{ $t('page_create_password.label_confirm_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Password"
rules="required" v-slot="{ errors }">
<input v-model="recoverPassword.newPasswordConfirm" placeholder="Confirm new password"
<input v-model="recoverPassword.newPasswordConfirm" :placeholder="$t('page_create_password.label_confirm_pass')"
type="password" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div>
<AuthButton icon="chevron-right" text="Update Password" :loading="isLoading" :disabled="isLoading"/>
<AuthButton icon="chevron-right" :text="$t('page_create_password.button_update')" :loading="isLoading" :disabled="isLoading"/>
</div>
</ValidationObserver>
<span class="additional-link">Remember your password? <b @click="goToAuthPage('log-in')">Log In.</b></span>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Registration-->
<AuthContent name="sign-up" :visible="false">
<img class="logo" src="/assets/images/hero.svg" alt="Vue File Manager logo">
<h1>Create New Account</h1>
<h2>Please fill registration to create account:</h2>
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_registration.title') }}</h1>
<h2>{{ $t('page_registration.subtitle') }}</h2>
<ValidationObserver @submit.prevent="signUp" ref="sign_up" v-slot="{ invalid }" tag="form"
class="form block-form">
<div class="block-wrapper">
<label>Email:</label>
<label>{{ $t('page_registration.label_email') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="register.email" placeholder="Type your E-mail" type="email"
<input v-model="register.email" :placeholder="$t('page_registration.placeholder_email')" type="email"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Full Name:</label>
<label>{{ $t('page_registration.label_name') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Full Name" rules="required"
v-slot="{ errors }">
<input v-model="register.name" placeholder="Type your full name" type="text"
<input v-model="register.name" :placeholder="$t('page_registration.placeholder_name')" type="text"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Create password:</label>
<label>{{ $t('page_registration.label_pass') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Your New Password"
rules="required" v-slot="{ errors }">
<input v-model="register.password" placeholder="Your new password" type="password"
<input v-model="register.password" :placeholder="$t('page_registration.placeholder_pass')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Confirm password:</label>
<label>{{ $t('page_registration.label_confirm_pass') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Your Password"
rules="required" v-slot="{ errors }">
<input v-model="register.password_confirmation" placeholder="Confirm your new password"
<input v-model="register.password_confirmation" :placeholder="$t('page_registration.placeholder_confirm_pass')"
type="password" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div>
<AuthButton icon="chevron-right" text="Create Account" :loading="isLoading" :disabled="isLoading"/>
<AuthButton icon="chevron-right" :text="$t('page_registration.button_create_account')" :loading="isLoading" :disabled="isLoading"/>
</div>
</ValidationObserver>
<span class="additional-link">Do you have an account? <b @click="goToAuthPage('log-in')">Log In.</b></span>
<span class="additional-link">{{ $t('page_registration.have_an_account') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Password reset link sended-->
<AuthContent name="password-reset-link-sended" :visible="false">
<img class="logo" src="/assets/images/hero.svg" alt="Vue File Manager logo">
<h1>Thank you!</h1>
<h2>We have e-mailed your password reset link!</h2>
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_forgotten_password.pass_sennded_title') }}</h1>
<h2>{{ $t('page_forgotten_password.pass_sennded_subtitle') }}</h2>
<span class="additional-link">Remember your password? <b @click="goToAuthPage('log-in')">Log In.</b></span>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Password reset successfully-->
<AuthContent name="password-reset-successfully" :visible="false">
<img class="logo" src="/assets/images/hero.svg" alt="Vue File Manager logo">
<h1>Awesome!</h1>
<h2>Your password was reset successfully.</h2>
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_forgotten_password.pass_reseted_title') }}</h1>
<h2>{{ $t('page_forgotten_password.pass_reseted_subtitle') }}</h2>
<AuthButton icon="chevron-right" @click.native="goToAuthPage('log-in')" text="Sign In"/>
<AuthButton icon="chevron-right" @click.native="goToAuthPage('log-in')" :text="$t('page_forgotten_password.pass_reseted_signin')"/>
</AuthContent>
</AuthContentWrapper>
</template>
@@ -320,7 +320,7 @@
if (error.response.status == 400) {
this.$refs.sign_in.setErrors({
'User Password': ['Sorry, you passed incorrect password :(']
'User Password': [this.$t('validation_errors.incorrect_password')]
});
}
@@ -460,7 +460,7 @@
let pathname = location.pathname.split('/')[1]
let token = location.search.split('token=')[1]
if (pathname === 'create-new-password') {
if (pathname === this.$t('routes.create_new_password')) {
this.recoverPassword.token = token
this.goToAuthPage('create-new-password')
} else {

View File

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

View File

@@ -1,14 +1,12 @@
<template>
<div @click="fileViewClick" @contextmenu.prevent.capture="contextMenu($event, undefined)" id="files-view" :class="filesViewWidth">
<ContextMenu/>
<MobileOptionList/>
<DesktopToolbar v-if="! $isMinimalScale()"/>
<FilesContainer/>
</div>
</template>
<script>
import MobileOptionList from '@/components/VueFileManagerComponents/FilesView/MobileOptionList'
import UploadProgress from '@/components/VueFileManagerComponents/FilesView/UploadProgress'
import FilesContainer from '@/components/VueFileManagerComponents/FilesView/FilesContainer'
import DesktopToolbar from '@/components/VueFileManagerComponents/FilesView/DesktopToolbar'
@@ -20,7 +18,6 @@
export default {
name: 'FilesView',
components: {
MobileOptionList,
UploadProgress,
FilesContainer,
DesktopToolbar,
@@ -91,7 +88,6 @@
<style lang="scss">
@import "@assets/app.scss";
#files-view {
font-family: 'Nunito', sans-serif;
font-size: 16px;
@@ -164,27 +160,21 @@
margin-bottom: 10px;
height: 90px;
&.file {
.file-icon {
@include font-size(75);
}
.file-icon-text {
@include font-size(12);
}
.file-icon {
@include font-size(75);
}
&.folder {
@include font-size(14);
.folder-icon {
margin-top: 0;
margin-bottom: 0;
}
.file-icon-text {
@include font-size(12);
}
&.image img {
.folder-icon {
@include font-size(75);
margin-top: 0;
margin-bottom: 0;
}
.image {
width: 90px;
height: 90px;
}

View File

@@ -1,26 +1,23 @@
<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>
@@ -38,7 +35,6 @@
return {
isVisibleWrapper: false,
buttonStyle: undefined,
isVisiblePopup: false,
message: undefined,
title: undefined,
button: undefined,
@@ -47,24 +43,18 @@
},
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 = 'Thats horrible!'
this.button = this.$t('alerts.error_confirm')
this.emoji = '😢😢😢'
this.buttonStyle = 'danger'
@@ -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,6 @@
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);
}
}
.popup-wrapper {
@@ -131,7 +110,7 @@
transform: translateY(-50%) scale(1);
margin: 0 auto;
padding: 40px;
box-shadow: 0 7px 250px rgba(25, 54, 60, 0.2);
box-shadow: $light_mode_popup_shadow;
border-radius: 8px;
text-align: center;
background: white;
@@ -180,12 +159,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 +186,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>

View File

@@ -16,7 +16,7 @@
.button-base {
@include font-size(16);
font-weight: 600;
font-weight: 700;
cursor: pointer;
transition: 0.15s all ease;
border-radius: 8px;

View File

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

View File

@@ -6,13 +6,22 @@
v-show="isVisible"
>
<ul class="menu-options" id="menu-options-list" ref="list" @click="closeAndResetContextMenu">
<li class="menu-option" @click="addToFavourites" v-if="! $isTrashLocation() && item && item.type === 'folder'">{{ isInFavourites ? 'Remove Favourite' : 'Add To Favourites' }}</li>
<li class="menu-option" @click="$store.dispatch('restoreItem', item)" v-if="item && $isTrashLocation()">Restore</li>
<li class="menu-option" @click="createFolder" v-if="! $isTrashLocation()">Create Folder</li>
<li class="menu-option" @click="removeItem" v-if="! $isTrashLocation() && item">Delete</li>
<li class="menu-option" @click="$store.dispatch('emptyTrash')" v-if="$isTrashLocation()">Empty Trash</li>
<li class="menu-option" @click="ItemDetail" v-if="item">Detail</li>
<li class="menu-option" @click="downloadItem" v-if="isFile || isImage">Download</li>
<!--View-->
<li class="menu-option" @click="addToFavourites" v-if="! $isTrashLocation() && item && isFolder">{{ isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites') }}</li>
<li class="menu-option" @click="createFolder" v-if="! $isTrashLocation()">{{ $t('context_menu.create_folder') }}</li>
<!--Edits-->
<li class="menu-option" @click="removeItem" v-if="item">{{ $t('context_menu.delete') }}</li>
<li class="menu-option" @click="moveItem" v-if="! $isTrashLocation() && item">{{ $t('context_menu.move') }}</li>
<!--Trash-->
<li class="menu-option" @click="$store.dispatch('restoreItem', item)" v-if="item && $isTrashLocation()">{{ $t('context_menu.restore') }}</li>
<li class="menu-option" @click="$store.dispatch('emptyTrash')" v-if="$isTrashLocation()">{{ $t('context_menu.empty_trash') }}</li>
<!--Others-->
<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>
@@ -25,11 +34,14 @@
name: 'ContextMenu',
computed: {
...mapGetters(['app']),
isFolder() {
return this.item && this.item.type === 'folder'
},
isFile() {
return this.item && this.item.type === 'file' ? true : false
return (this.item && this.item.type !== 'folder') && (this.item && this.item.type !== 'image')
},
isImage() {
return this.item && this.item.type === 'image' ? true : false
return this.item && this.item.type === 'image'
},
isInFavourites() {
return this.app.favourites.find(el => el.unique_id == this.item.unique_id)
@@ -44,6 +56,10 @@
}
},
methods: {
moveItem() {
// Move item fire popup
events.$emit('popup:move-item', this.item);
},
addToFavourites() {
if (this.app.favourites && ! this.app.favourites.find(el => el.unique_id == this.item.unique_id)) {
this.$store.dispatch('addToFavourites', this.item)
@@ -71,7 +87,7 @@
},
createFolder() {
// Create folder
this.$createFolder('New Folder')
this.$createFolder(this.$t('popup_create_folder.folder_default_name'))
},
closeAndResetContextMenu() {
// Close context menu
@@ -128,8 +144,7 @@
@import "@assets/app.scss";
.contextmenu {
max-width: 190px;
width: 190px;
min-width: 190px;
position: absolute;
z-index: 99;
box-shadow: $shadow;
@@ -148,7 +163,8 @@
padding: 0;
.menu-option {
font-weight: 600;
white-space: nowrap;
font-weight: 700;
@include font-size(15);
padding: 15px 30px;
cursor: pointer;

View File

@@ -86,6 +86,9 @@
},
preview() {
return this.preview_type === 'list' ? 'th' : 'th-list'
},
isTrash() {
return this.currentFolder.location === 'trash' || this.currentFolder.location === 'trash-root'
}
},
data() {
@@ -112,7 +115,7 @@
events.$emit('items:delete')
},
createFolder() {
this.$createFolder()
if (! this.isTrash) this.$createFolder()
}
},
created() {
@@ -147,7 +150,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 +168,7 @@
.back-directory-title {
line-height: 1;
font-weight: 600;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;

View File

@@ -2,16 +2,16 @@
<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>
<h1 class="title">{{ $t('empty_page.title') }}</h1>
<p v-if="! isTrash" class="description">
Upload some files here easily via upload button
{{ $t('empty_page.description') }}
</p>
<ButtonUpload
v-if="! isTrash"
@input.native="$uploadFiles(files)"
v-model="files"
button-style="theme"
>Upload File
>{{ $t('empty_page.call_to_action') }}
</ButtonUpload
>
</div>
@@ -40,7 +40,7 @@
return this.data.length == 0
},
isTrash() {
return typeof this.currentFolder.unique_id === 'undefined'
return this.currentFolder.location === 'trash' || this.currentFolder.location === 'trash-root'
}
},
data() {
@@ -78,7 +78,7 @@
.title {
@include font-size(24);
color: $text;
font-weight: 600;
font-weight: 700;
margin: 0;
}

View File

@@ -1,31 +1,18 @@
<template>
<div v-if="fileInfoDetail">
<div class="file-headline" spellcheck="false">
<!--Image thumbnail-->
<div v-if="fileInfoDetail.type == 'image'" class="image-preview">
<img
@dblclick="$openImageOnNewTab(fileInfoDetail.file_url)"
:src="fileInfoDetail.thumbnail"
:alt="fileInfoDetail.name"
/>
</div>
<FilePreview />
<!--File info-->
<div class="flex">
<div class="icon">
<div class="icon-preview" @dblclick="getItemAction">
<FontAwesomeIcon
v-if="fileInfoDetail.type == 'folder'"
icon="folder"
></FontAwesomeIcon>
<FontAwesomeIcon
v-if="fileInfoDetail.type == 'file'"
icon="file"
></FontAwesomeIcon>
<FontAwesomeIcon
v-if="fileInfoDetail.type == 'image'"
icon="file-image"
></FontAwesomeIcon>
<FontAwesomeIcon v-if="fileInfoDetail.type == 'folder'" icon="folder"></FontAwesomeIcon>
<FontAwesomeIcon v-if="fileInfoDetail.type == 'file'" icon="file"></FontAwesomeIcon>
<FontAwesomeIcon v-if="fileInfoDetail.type == 'image'" icon="file-image"></FontAwesomeIcon>
<FontAwesomeIcon v-if="fileInfoDetail.type == 'video'" icon="file-video"></FontAwesomeIcon>
<FontAwesomeIcon v-if="fileInfoDetail.type == 'audio'" icon="file-audio"></FontAwesomeIcon>
</div>
</div>
<div class="file-info">
@@ -41,37 +28,47 @@
<ul class="list-info">
<!--Filesize-->
<li v-if="fileInfoDetail.filesize" class="list-info-item">
<b>Size</b>
<b>{{ $t('file_detail.size') }}</b>
<span>{{ fileInfoDetail.filesize }}</span>
</li>
<!--Latest change-->
<li v-if="fileInfoDetail.created_at" class="list-info-item">
<b>Created at</b>
<b>{{ $t('file_detail.created_at') }}</b>
<span>{{ fileInfoDetail.created_at }}</span>
</li>
<!--Parent-->
<li class="list-info-item">
<b>Where</b>
<span>{{
fileInfoDetail.parent ? fileInfoDetail.parent.name : 'Home'
}}</span>
<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>
</ul>
</div>
</template>
<script>
import FilePreview from '@/components/VueFileManagerComponents/FilesView/FilePreview'
import {mapGetters} from 'vuex'
import {debounce} from 'lodash'
import {events} from "@/bus"
export default {
name: 'FilesInfoPanel',
name: 'FileInfoPanel',
components: {
FilePreview
},
computed: {
...mapGetters(['fileInfoDetail'])
},
methods: {
moveItem() {
// Move item fire popup
events.$emit('popup:move-item', this.fileInfoDetail);
},
getItemAction() {
// Open image on new tab
if (this.fileInfoDetail.type == 'image') {
@@ -91,7 +88,6 @@
// Open folder
if (this.fileInfoDetail.type == 'folder') {
// Todo: open folder
console.log('Open folder')
}
},
changeItemName: debounce(function (e) {
@@ -117,20 +113,6 @@
margin-bottom: 20px;
border-radius: 8px;
.image-preview {
width: 100%;
display: block;
margin-bottom: 7px;
img {
border-radius: 4px;
overflow: hidden;
width: 100%;
object-fit: cover;
cursor: pointer;
}
}
.flex {
display: flex;
align-items: top;
@@ -172,8 +154,8 @@
word-break: break-all;
.name {
@include font-size(16);
font-weight: 600;
@include font-size(14);
font-weight: 700;
color: $text;
}
@@ -197,6 +179,16 @@
padding-top: 0;
}
.action-button {
cursor: pointer;
.icon {
@include font-size(11);
display: inline-block;
margin-right: 2px;
}
}
b {
display: block;
@include font-size(13);
@@ -204,8 +196,8 @@
}
span {
display: block;
@include font-size(16);
display: inline-block;
@include font-size(14);
font-weight: bold;
color: $text;
}
@@ -236,6 +228,13 @@
span {
color: $dark_mode_text_primary
}
.action-button {
.icon {
color: $dark_mode_text_primary;
}
}
}
}
}

View File

@@ -7,7 +7,7 @@
>
<!--Grid preview-->
<div
draggable="true"
:draggable="! isDeleted"
@dragstart="$emit('dragstart')"
@drop="
$emit('drop')
@@ -19,7 +19,7 @@
: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
@@ -29,15 +29,10 @@
<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-->
@@ -48,16 +43,16 @@
@input="changeItemName"
:contenteditable="!$isMobile()"
class="name"
>{{ item.name }}</span
>{{ itemName }}</span
>
<!--Other attributes-->
<span v-if="isFile || isImage" class="item-size">{{
<span v-if="! isFolder" class="item-size">{{
data.filesize
}}</span>
<span v-if="isFolder" class="item-length">
{{ folderItems == 0 ? 'Empty' : (folderItems + ' item') | pluralize(folderItems) }}
{{ folderItems == 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }}
</span>
</div>
@@ -82,13 +77,13 @@
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'
},
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,16 +92,11 @@
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: {
@@ -126,6 +116,10 @@
},
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) {
@@ -165,6 +159,7 @@
}
},
changeItemName: debounce(function (e) {
// Prevent submit empty string
if (e.target.innerText === '') return
@@ -176,20 +171,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 +202,6 @@
}
}
.file-wrapper {
position: relative;
text-align: center;
@@ -227,7 +218,7 @@
.item-size,
.item-length {
@include font-size(12);
font-weight: 100;
font-weight: 400;
color: $text-muted;
display: block;
}
@@ -235,6 +226,11 @@
.name {
display: block;
&[contenteditable] {
-webkit-user-select: text;
user-select: text;
}
&[contenteditable='true']:hover {
text-decoration: underline;
}
@@ -242,7 +238,7 @@
.name {
color: $text;
@include font-size(15);
@include font-size(14);
font-weight: 700;
max-height: 40px;
overflow: hidden;
@@ -285,6 +281,7 @@
}
.icon-item {
text-align: center;
position: relative;
height: 110px;
margin-bottom: 20px;
@@ -306,41 +303,33 @@
}
}
&.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;
}
.folder-icon {
align-items: flex-end;
@include font-size(80);
margin: 0 auto;

View File

@@ -6,7 +6,7 @@
>
<!--List preview-->
<div
draggable="true"
:draggable="! isDeleted"
@dragstart="$emit('dragstart')"
@drop="
$emit('drop')
@@ -18,7 +18,7 @@
: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
@@ -28,15 +28,10 @@
<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-->
@@ -47,14 +42,13 @@
@input="changeItemName"
:contenteditable="!$isMobile() && !$isTrashLocation()"
class="name"
>{{ item.name }}</span
>
>{{ itemName }}</span>
<!--Other attributes-->
<span v-if="isFile || isImage" class="item-size">{{ data.filesize }}, {{ timeStamp }}</span>
<span v-if="! isFolder" class="item-size">{{ data.filesize }}, {{ timeStamp }}</span>
<span v-if="isFolder" class="item-length">
{{ folderItems == 0 ? 'Empty' : (folderItems + ' Item') | pluralize(folderItems) }}, {{ timeStamp }}
{{ folderItems == 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }}, {{ timeStamp }}
</span>
</div>
@@ -82,13 +76,13 @@
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'
},
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 +92,6 @@
}
},
filters: {
pluralize(word, amount) {
return amount > 1 ? word + 's' : word
},
limitCharacters(str) {
if (str.length > 3) {
@@ -115,7 +106,7 @@
return {
isClicked: false,
area: false,
item: undefined,
itemName: undefined,
}
},
methods: {
@@ -137,6 +128,10 @@
},
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) {
@@ -176,6 +171,7 @@
}
},
changeItemName: debounce(function (e) {
// Prevent submit empty string
if (e.target.innerText === '') return
@@ -187,20 +183,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>
@@ -243,14 +236,18 @@
.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 +256,7 @@
.name {
color: $text;
@include font-size(15);
@include font-size(14);
font-weight: 700;
max-height: 40px;
overflow: hidden;
@@ -278,6 +275,7 @@
}
.icon-item {
text-align: center;
position: relative;
flex: 0 0 50px;
line-height: 0;
@@ -307,38 +305,32 @@
}
}
&.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;
}
}

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

View File

@@ -1,5 +1,10 @@
<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"
@@ -18,7 +23,10 @@
<MobileActions v-if="$isMinimalScale()" />
<!--Item previews list-->
<div v-if="isList" class="file-list-wrapper">
<div
v-if="isList"
class="file-list-wrapper"
>
<transition-group
name="file"
tag="section"
@@ -27,8 +35,7 @@
>
<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"
@@ -48,8 +55,7 @@
>
<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"
@@ -65,7 +71,7 @@
<!--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>
@@ -81,7 +87,7 @@
<!--If file info panel empty show message-->
<EmptyMessage
v-if="!fileInfoDetail"
message="There is nothing to preview."
:message="$t('messages.nothing_to_preview')"
icon="eye-slash"
/>
</div>
@@ -135,10 +141,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 +165,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')
}
},
@@ -228,6 +257,10 @@
.file-content {
display: flex;
flex-wrap: nowrap;
&.is-dragging {
@include transform(scale(0.99));
}
}
.files-container {

View File

@@ -1,10 +1,10 @@
<template>
<div id="mobile-actions-wrapper">
<div class="mobile-actions">
<MobileActionButton v-if="! $isTrashLocation()" @click.native="createFolder" icon="folder-plus" text="Add Folder"></MobileActionButton>
<MobileActionButtonUpload v-if="! $isTrashLocation()" @input.native="$uploadFiles" icon="upload" text="Upload"></MobileActionButtonUpload>
<MobileActionButton v-if="! $isTrashLocation()" @click.native="createFolder" icon="folder-plus" :text="$t('context_menu.add_folder')"></MobileActionButton>
<MobileActionButtonUpload v-if="! $isTrashLocation()" @input.native="$uploadFiles" icon="upload" :text="$t('context_menu.upload')"></MobileActionButtonUpload>
<MobileActionButton @click.native="switchPreview" :icon="previewIcon" :text="previewText"></MobileActionButton>
<MobileActionButton v-if="$isTrashLocation()" @click.native="$store.dispatch('emptyTrash')" icon="trash-alt" text="Empty Trash"></MobileActionButton>
<MobileActionButton v-if="$isTrashLocation()" @click.native="$store.dispatch('emptyTrash')" icon="trash-alt" :text="$t('context_menu.empty_trash')"></MobileActionButton>
</div>
<UploadProgress />
</div>
@@ -31,7 +31,7 @@
return this.preview_type === 'list' ? 'th' : 'th-list'
},
previewText() {
return this.preview_type === 'list' ? 'Grid' : 'List'
return this.preview_type === 'list' ? this.$t('preview_type.grid') : this.$t('preview_type.list')
}
},
methods: {
@@ -40,13 +40,14 @@
},
createFolder() {
if (this.$isMobile()) {
let folderName = prompt('Please enter your new folder name')
// Get folder name
let folderName = prompt(this.$t('popup_create_folder.title'))
// Create folder
if (folderName) this.$createFolder(folderName)
} else {
// Create folder
this.$createFolder('New Folder')
this.$createFolder(this.$t('popup_create_folder.folder_default_name'))
}
},
}

View File

@@ -2,7 +2,7 @@
<div class="options-wrapper">
<transition name="context-menu">
<div
v-show="isVisible"
v-if="isVisible"
ref="contextmenu"
class="options"
@click="closeAndResetContextMenu"
@@ -11,37 +11,44 @@
<ul class="menu-options">
<li class="menu-option"
@click="addToFavourites"
v-if="! $isTrashLocation() && fileInfoDetail && fileInfoDetail.type === 'folder'"
v-if="! $isTrashLocation() && fileInfoDetail && isFolder"
>
{{ isInFavourites ? 'Remove Favourite' : 'Add To Favourites' }}
{{ isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites') }}
</li>
<li class="menu-option"
@click="$store.dispatch('restoreItem', fileInfoDetail)"
v-if="fileInfoDetail && $isTrashLocation()"
>
Restore
{{ $t('context_menu.restore') }}
</li>
<li
class="menu-option"
@click="renameItem"
v-if="fileInfoDetail"
>
Rename
{{ $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="isFile || isImage"
v-if="! isFolder"
>
Download
{{ $t('context_menu.download') }}
</li>
<li
class="menu-option delete"
@click="removeItem"
v-if="fileInfoDetail"
>
Delete
{{ $t('context_menu.delete') }}
</li>
</ul>
</div>
@@ -69,19 +76,13 @@
return this.app.favourites.find(el => el.unique_id == this.fileInfoDetail.unique_id)
},
isFile() {
return this.fileInfoDetail && this.fileInfoDetail.type === 'file'
? true
: false
return (this.fileInfoDetail && this.fileInfoDetail.type !== 'folder') && (this.fileInfoDetail && this.fileInfoDetail.type !== 'image')
},
isImage() {
return this.fileInfoDetail && this.fileInfoDetail.type === 'image'
? true
: false
},
isFolder() {
return this.fileInfoDetail && this.fileInfoDetail.type === 'folder'
? true
: false
}
},
data() {
@@ -90,6 +91,10 @@
}
},
methods: {
moveItem() {
// Move item fire popup
events.$emit('popup:move-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)
@@ -110,16 +115,24 @@
},
renameItem() {
let itemName = prompt(
'Change your item name',
this.$t('popup_rename.title'),
this.fileInfoDetail.name
)
if (itemName && itemName !== '') {
this.$store.dispatch('changeItemName', {
let item = {
unique_id: this.fileInfoDetail.unique_id,
type: this.fileInfoDetail.type,
name: itemName
})
}
this.$store.dispatch('changeItemName', item)
// Change item name if is mobile device or prompted
if ( this.$isMobile() ) {
events.$emit('change:name', item)
}
}
},
closeAndResetContextMenu() {
@@ -130,15 +143,13 @@
}
},
created() {
// Show context menu
events.$on('mobileMenu:show', () => {
// Show context menu
this.isVisible = !this.isVisible
})
events.$on('mobileMenu:hide', () => {
this.isVisible = false
})
// Hide mobile menu
events.$on('mobileMenu:hide', () => {
this.isVisible = false
})
@@ -150,7 +161,7 @@
@import "@assets/app.scss";
.vignette {
background: rgba(0, 0, 0, 0.25);
background: rgba(0, 0, 0, 0.15);
position: absolute;
top: 0;
right: 0;
@@ -173,26 +184,24 @@
display: block;
}
.menu-wrapper {
margin: 15px;
}
.menu-options {
margin-top: 10px;
box-shadow: $shadow;
background: white;
border-radius: 8px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
list-style: none;
width: 100%;
.menu-option {
font-weight: 600;
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_background;
border-bottom: 1px solid $light_mode_border;
&:last-child {
border: none;
@@ -210,10 +219,10 @@
.options {
.menu-options {
background: $dark_mode_foreground;
background: $dark_mode_background;
.menu-option {
border-color: rgba($dark_mode_background, .5);
border-color: $dark_mode_border_color;
color: $dark_mode_text_primary;
}
}
@@ -223,12 +232,12 @@
// Transition
.context-menu-enter-active,
.fade-enter-active {
transition: all 300ms ease;
transition: all 200ms;
}
.context-menu-leave-active,
.fade-leave-active {
transition: all 300ms;
transition: all 200ms;
}
.fade-enter,

View File

@@ -130,9 +130,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;

View File

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

View File

@@ -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>
@@ -88,6 +88,7 @@
&::placeholder {
color: $text;
@include font-size(14);
font-weight: 400;
}
&:focus {

View File

@@ -1,45 +1,45 @@
<template>
<div id="loading-bar-spinner" class="spinner">
<div class="spinner-icon"></div>
</div>
<div id="loading-bar-spinner" class="spinner">
<div class="spinner-icon"></div>
</div>
</template>
<script>
export default {
name: 'Spinner'
}
export default {
name: 'Spinner'
}
</script>
<style scoped lang="scss">
@import "@assets/app.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 {
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%;
}
#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);
}
}
@keyframes loading-bar-spinner {
0% {
transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>

View File

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

View File

@@ -0,0 +1,299 @@
<template>
<transition name="popup">
<div class="popup" @click.self="closePopup" v-if="isVisibleWrapper">
<div class="popup-wrapper">
<!--Title-->
<div class="popup-header">
<h1 class="title">{{ $t('popup_move_item.title') }}</h1>
<!--<p v-if="message" class="message">{{ message }}</p>-->
</div>
<!--Content-->
<div class="popup-content" v-if="app && pickedItem">
<Spinner v-if="isLoadingTree"/>
<div v-if="! isLoadingTree">
<ThumbnailItem class="item-thumbnail" :file="pickedItem"/>
<TreeMenu :depth="1" :nodes="items" v-for="items in app.folders" :key="items.unique_id"/>
</div>
</div>
<!--Actions-->
<div class="actions">
<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>
</div>
</div>
</div>
</transition>
</template>
<script>
import ThumbnailItem from '@/components/VueFileManagerComponents/Others/ThumbnailItem'
import ButtonBase from '@/components/VueFileManagerComponents/FilesView/ButtonBase'
import Spinner from '@/components/VueFileManagerComponents/FilesView/Spinner'
import TreeMenu from '@/components/VueFileManagerComponents/Others/TreeMenu'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
export default {
name: 'PopupMoveItem',
components: {
ThumbnailItem,
ButtonBase,
TreeMenu,
Spinner,
},
computed: {
...mapGetters(['app']),
},
data() {
return {
isVisibleWrapper: false,
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')
},
closePopup() {
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 popup
events.$on('popup:move-item', item => {
// Show tree spinner
this.isLoadingTree = true
// Get folder tree and hide spinner
this.$store.dispatch('getFolderTree').then(() => {
this.isLoadingTree = false
}).catch(() => {
this.isLoadingTree = false
})
// Make popup visible
this.isVisibleWrapper = true
// Store picked item
this.pickedItem = item
})
// Close popup
events.$on('popup:close', () => {
// Hide popup wrapper
this.isVisibleWrapper = false
// Clear selected folder
this.selectedFolder = undefined
})
}
}
</script>
<style scoped lang="scss">
@import "@assets/app.scss";
.popup {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 20;
overflow-y: auto;
display: grid;
padding: 40px;
}
.popup-wrapper {
box-shadow: $light_mode_popup_shadow;
border-radius: 8px;
background: white;
margin: auto;
width: 480px;
z-index: 12;
}
.popup-header {
padding: 20px;
.title {
@include font-size(18);
font-weight: 700;
color: $text;
}
.message {
@include font-size(16);
color: #8b8f9a;
margin-top: 5px;
}
}
.popup-content {
height: 400px;
overflow-y: auto;
}
.item-thumbnail {
margin-bottom: 20px;
}
.actions {
padding: 20px;
margin: 0 -10px;
display: flex;
.popup-button {
width: 100%;
margin: 0 10px;
}
}
// Desktop, tablet
.medium, .large {
// Animations
.popup-enter-active {
animation: popup-in 0.35s 0.15s ease both;
}
.popup-leave-active {
animation: popup-in 0.15s ease reverse;
}
}
// Mobile styles
.small {
.popup {
overflow: hidden;
}
.popup-wrapper {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
transform: translateY(0) scale(1);
box-shadow: none;
width: 100%;
border-radius: 0px;
.popup-content {
top: 57px;
bottom: 72px;
position: absolute;
left: 0;
right: 0;
height: initial;
}
.actions {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
}
.popup-header {
padding: 15px;
}
.actions {
padding: 15px;
}
// Animations
.popup-enter-active {
animation: popup-slide-in 0.35s 0.15s ease both;
}
.popup-leave-active {
animation: popup-slide-in 0.15s ease reverse;
}
}
@keyframes popup-in {
0% {
opacity: 0;
transform: scale(0.7);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes popup-slide-in {
0% {
transform: translateY(100%);
}
100% {
transform: translateY(0);
}
}
// Dark mode
@media (prefers-color-scheme: dark) {
.popup-wrapper {
background: $dark_mode_background;
box-shadow: $dark_mode_popup_shadow;
}
.popup-header {
.title {
color: $dark_mode_text_primary;
}
.message {
color: $dark_mode_text_secondary;
}
}
}
@media (prefers-color-scheme: dark) and (max-width: 690px) {
.popup-wrapper {
background: $dark_mode_background;
}
}
</style>

View File

@@ -15,10 +15,16 @@
.text-label {
@include font-size(10);
color: $light_text;
color: $theme;
text-transform: uppercase;
font-weight: 900;
display: block;
margin-bottom: 5px;
}
@media (prefers-color-scheme: dark) {
.text-label {
color: rgba($dark_mode_text_secondary, .4);
}
}
</style>

View File

@@ -0,0 +1,177 @@
<template>
<div class="file-item">
<!--Thumbnail for item-->
<div class="icon-item">
<!--If is file or image, then link item-->
<span v-if="isFile" class="file-icon-text">{{ file.mimetype }}</span>
<!--Folder thumbnail-->
<FontAwesomeIcon v-if="isFile" class="file-icon" icon="file"/>
<!--Image thumbnail-->
<img v-if="isImage" class="image" :src="file.thumbnail" :alt="file.name"/>
<!--Else show only folder icon-->
<FontAwesomeIcon v-if="isFolder" class="folder-icon" icon="folder"/>
</div>
<!--Name-->
<div class="item-name">
<!--Name-->
<span class="name">{{ file.name }}</span>
<!--Other attributes-->
<span class="subtitle">{{ $t('item_thumbnail.original_location') }}: {{ currentFolder.name }}</span>
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: 'ThumbnailItem',
props: ['file'],
computed: {
...mapGetters(['currentFolder']),
isFolder() {
return this.file.type === 'folder'
},
isFile() {
return this.file.type !== 'folder' && this.file.type !== 'image'
},
isImage() {
return this.file.type === 'image'
}
},
}
</script>
<style scoped lang="scss">
@import "@assets/app.scss";
.file-item {
display: flex;
align-items: center;
padding: 0 20px;
.item-name {
display: block;
margin-left: 10px;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.subtitle {
@include font-size(11);
font-weight: 400;
color: $text-muted;
display: block;
}
.name {
white-space: nowrap;
color: $text;
@include font-size(14);
font-weight: 700;
max-height: 40px;
overflow: hidden;
text-overflow: ellipsis;
}
}
.icon-item {
position: relative;
min-width: 40px;
text-align: center;
line-height: 0;
.file-icon {
@include font-size(35);
path {
fill: #fafafc;
stroke: #dfe0e8;
stroke-width: 1;
}
}
.folder-icon {
@include font-size(36);
path {
fill: $theme;
}
}
.file-icon-text {
line-height: 1;
top: 40%;
@include font-size(9);
margin: 0 auto;
position: absolute;
text-align: center;
left: 0;
right: 0;
color: $theme;
font-weight: 600;
user-select: none;
max-width: 20px;
max-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.image {
object-fit: cover;
user-select: none;
max-width: 100%;
border-radius: 5px;
width: 36px;
height: 36px;
}
}
}
.small {
.file-item {
padding: 0 15px;
margin-bottom: 10px;
}
}
@media (prefers-color-scheme: dark) {
.file-item {
.icon-item .file-icon {
path {
fill: $dark_mode_background;
stroke: #2F3C54;
}
}
.item-name .name {
color: $dark_mode_text_primary;
}
}
}
@media (max-width: 690px) and (prefers-color-scheme: dark) {
.file-item {
.icon-item .file-icon {
path {
fill: $dark_mode_foreground;
}
}
}
}
</style>

View File

@@ -0,0 +1,188 @@
<template>
<!--Folder Icon-->
<div class="folder-item-wrapper">
<div class="folder-item" :class="{'is-selected': isSelected}" @click="showTree" :style="indent">
<FontAwesomeIcon class="icon-chevron" :class="{'is-opened': isVisible, 'is-visible': nodes.folders.length !== 0}" icon="chevron-right"/>
<FontAwesomeIcon class="icon" :icon="directoryIcon"/>
<span class="label">{{ nodes.name }}</span>
</div>
<TreeMenu :depth="depth + 1" v-if="isVisible" :nodes="item" v-for="item in nodes.folders" :key="item.unique_id" />
</div>
</template>
<script>
import TreeMenu from '@/components/VueFileManagerComponents/Others/TreeMenu'
import {events} from "@/bus"
export default {
name: 'TreeMenu',
props: [
'nodes', 'depth'
],
components: {
TreeMenu,
},
computed: {
indent() {
return { paddingLeft: this.depth * 25 + 'px' }
},
directoryIcon() {
if (this.nodes.location === 'base') {
return 'hdd'
} else {
return 'folder'
}
}
},
data() {
return {
isVisible: false,
isSelected: false,
}
},
methods: {
showTree() {
this.isVisible = ! this.isVisible
events.$emit('pick-folder', this.nodes)
}
},
created() {
// Show first location
if (this.depth == 1) this.isVisible = true
// Select clicked folder
events.$on('pick-folder', node => {
this.isSelected = false
if (this.nodes.unique_id == node.unique_id) this.isSelected = true
})
}
}
</script>
<style lang="scss" scoped>
@import "@assets/app.scss";
.folder-item {
display: block;
padding: 15px 20px;
@include transition(150ms);
cursor: pointer;
position: relative;
white-space: nowrap;
border-bottom: 1px solid $light_mode_border;
.icon {
@include font-size(18);
margin-right: 9px;
vertical-align: middle;
path {
fill: $text;
}
}
.icon-chevron {
@include transition(300ms);
@include font-size(13);
margin-right: 9px;
vertical-align: middle;
opacity: 0;
&.is-visible {
opacity: 1;
}
&.is-opened {
@include transform(rotate(90deg));
}
path {
fill: rgba($text, 0.25);
}
}
.label {
@include font-size(15);
font-weight: 700;
vertical-align: middle;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
color: $text;
}
&:hover {
background: $light_background;
}
&.is-selected {
background: rgba($theme, .1);
.icon {
path {
fill: $theme;
}
}
.label {
color: $theme;
}
}
}
// Dark mode
@media (prefers-color-scheme: dark) {
.folder-item {
border-bottom: 1px solid $dark_mode_border_color;
.label {
color: $dark_mode_text_primary;
}
&:hover {
background: $dark_mode_foreground;
}
&.is-selected {
background: rgba($theme, .1);
}
.icon {
path {
fill: lighten($dark_mode_foreground, 10%);
}
}
.icon-chevron {
path {
fill: $theme;
}
}
}
&.is-selected {
background: rgba($theme, .1);
}
}
@media (prefers-color-scheme: dark) and (max-width: 690px) {
.folder-item {
&:hover,
&.is-selected {
background: rgba($theme, .1);
}
}
}
</style>

View File

@@ -48,7 +48,7 @@
// Update user avatar
this.$updateImage('/user/profile', 'avatar', event.target.files[0])
} else {
alert('You may have uploaded the wrong file, try again!')
alert( this.$t('validation_errors.wrong_image') )
}
}
},

View File

@@ -0,0 +1,74 @@
<template>
<transition name="vignette">
<div v-if="isVisibleVignette" class="vignette" @click="closePopup"></div>
</transition>
</template>
<script>
import {events} from '@/bus'
export default {
name: 'Vignette',
data() {
return {
isVisibleVignette: false,
}
},
methods: {
closePopup() {
events.$emit('popup:close')
events.$emit('mobileMenu:hide')
}
},
created() {
// Hide vignette
events.$on('popup:close', () => this.isVisibleVignette = false)
// Show vignette
events.$on('popup:move-item', () => this.isVisibleVignette = true)
events.$on('alert:open', () => this.isVisibleVignette = true)
events.$on('success:open', () => this.isVisibleVignette = true)
}
}
</script>
<style lang="scss" scoped>
@import "@assets/app.scss";
.vignette {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 19;
background: $light_mode_vignette;
}
// Dark mode
@media (prefers-color-scheme: dark) {
.vignette {
background: $dark_mode_vignette;
}
}
.vignette-enter-active {
animation: vignette-in 0.35s ease;
}
.vignette-leave-active {
animation: vignette-in 0.15s ease reverse;
}
@keyframes vignette-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>

View File

@@ -9,11 +9,11 @@
<!--Locations-->
<div class="menu-list-wrapper">
<TextLabel>Locations</TextLabel>
<TextLabel>{{ $t('sidebar.locations') }}</TextLabel>
<ul class="menu-list">
<li class="menu-list-item" @click="goHome">
<FontAwesomeIcon class="icon" icon="hdd"/>
<span class="label">Home</span>
<span class="label">{{ $t('locations.home') }}</span>
</li>
<!--<li class="menu-list-item">
<FontAwesomeIcon class="icon" icon="share"/>
@@ -21,7 +21,7 @@
</li>-->
<li class="menu-list-item" @click="getTrash">
<FontAwesomeIcon class="icon" icon="trash-alt"/>
<span class="label">Trash</span>
<span class="label">{{ $t('locations.trash') }}</span>
</li>
</ul>
</div>
@@ -33,10 +33,10 @@
@drop="dragFinish($event)"
:class="{ 'is-dragenter': area }"
>
<TextLabel>Favourites</TextLabel>
<TextLabel>{{ $t('sidebar.favourites') }}</TextLabel>
<transition-group tag="ul" class="menu-list" name="folder-item">
<li class="empty-list" v-if="app.favourites.length == 0" :key="0">Drag here your favourite
folder.
<li class="empty-list" v-if="app.favourites.length == 0" :key="0">
{{ $t('sidebar.favourites_empty') }}
</li>
<li @click.stop="openFolder(folder)" class="menu-list-item" v-for="folder in app.favourites"
@@ -52,9 +52,9 @@
<!--Last Uploads-->
<div class="menu-list-wrapper">
<TextLabel>Last Uploads</TextLabel>
<TextLabel>{{ $t('sidebar.latest') }}</TextLabel>
<p class="empty-list" v-if="app.latest_uploads.length == 0">You don't have any latest uploads.</p>
<p class="empty-list" v-if="app.latest_uploads.length == 0">{{ $t('sidebar.latest_empty') }}</p>
<FileListItemThumbnail @dblclick.native="downloadFile(item)" @click.native="showFileDetail(item)" :file="item" v-for="item in app.latest_uploads" :key="item.unique_id"/>
</div>
@@ -64,7 +64,7 @@
<StorageSize v-if="config.storageLimit"/>
<div v-if="isSmallAppSize" class="log-out-button">
<ButtonBase @click.native="$store.dispatch('logOut')" button-style="danger">Log Out</ButtonBase>
<ButtonBase @click.native="$store.dispatch('logOut')" button-style="danger">{{ $t('context_menu.log_out') }}</ButtonBase>
</div>
</div>
</transition>
@@ -176,8 +176,8 @@
#sidebar {
position: relative;
flex: 0 0 295px;
border-right: 1px solid $light_background;
flex: 0 0 265px;
background: $light_background;
}
.content-scroller {
@@ -198,37 +198,18 @@
}
.menu-list-wrapper {
margin-bottom: 25px;
margin-bottom: 20px;
.menu-list {
.menu-list-item {
display: block;
padding: 10px 15px 10px 25px;
padding: 8px 15px 8px 25px;
@include transition(150ms);
cursor: pointer;
position: relative;
white-space: nowrap;
&:hover {
background: rgba($theme, .1);
//background: $light_background;
.icon {
path {
fill: $theme;
}
}
.label {
color: $theme;
}
.delete-icon {
display: block;
}
}
.icon {
@include font-size(13);
width: 15px;
@@ -254,7 +235,7 @@
}
.label {
@include font-size(15);
@include font-size(14);
font-weight: 700;
vertical-align: middle;
white-space: nowrap;
@@ -263,6 +244,24 @@
text-overflow: ellipsis;
display: inline-block;
}
&:hover {
background: rgba($theme, .1);
.icon {
path {
fill: $theme;
}
}
.label {
color: $theme;
}
.delete-icon {
display: block;
}
}
}
}
@@ -280,16 +279,27 @@
border: 2px dashed transparent;
.menu-list-item {
padding: 10px 13px 10 23px;
padding: 8px 23px;
.icon {
@include font-size(20);
margin-right: 5px;
@include font-size(14);
width: 20px;
path {
fill: $theme;
}
}
&:hover {
background: rgba($theme, .1);
.icon {
path {
fill: $theme;
}
}
}
}
}
}
@@ -356,7 +366,7 @@
padding: 10px 26px;
.label {
@include font-size(16);
@include font-size(14);
}
}
}
@@ -367,8 +377,8 @@
}
@media (prefers-color-scheme: dark) {
#sidebar {
border-color: $dark_mode_foreground;
background: $dark_mode_foreground;
}
@@ -380,18 +390,22 @@
color: $dark_mode_text_primary;
}
.icon {
path {
fill: lighten($dark_mode_foreground, 10%);
}
}
&:hover {
background: rgba($theme, .1);
}
}
}
}
@media (prefers-color-scheme: dark) and (max-width: 690px){
@media (prefers-color-scheme: dark) and (max-width: 690px) {
#sidebar {
border-color: $dark_mode_background;
background: $dark_mode_background;
}
}

View File

@@ -2,7 +2,7 @@
<div class="file-item">
<!--Thumbnail for item-->
<div class="icon-item" :class="file.type">
<div class="icon-item">
<!--If is file or image, then link item-->
<span v-if="isFile" class="file-icon-text">{{ file.mimetype }}</span>
@@ -11,10 +11,10 @@
<FontAwesomeIcon v-if="isFile" class="file-icon" icon="file" />
<!--Image thumbnail-->
<img v-if="isImage" :src="file.thumbnail" :alt="file.name" />
<img v-if="isImage" class="image" :src="file.thumbnail" :alt="file.name" />
<!--Else show only folder icon-->
<FontAwesomeIcon v-if="isFolder" class="folder-icon" icon="folder" />
<FontAwesomeIcon v-if="isFolder" class="folder-icon" icon="folder" />
</div>
<!--Name-->
@@ -24,9 +24,9 @@
<span class="name" >{{ file.name }}</span>
<!--Other attributes-->
<span v-if="isFile || isImage" class="item-size">{{ file.filesize }}, {{ file.created_at }}</span>
<span v-if="! isFolder" class="item-size">{{ file.filesize }}, {{ file.created_at }}</span>
<span v-if="isFolder" class="item-length">{{ file.items == 0 ? 'Empty' : (file.items + ' item') | pluralize(file.items) }}, {{ file.created_at }}</span >
<span v-if="isFolder" class="item-length">{{ file.items == 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }}, {{ file.created_at }}</span>
</div>
</div>
</template>
@@ -41,28 +41,22 @@ export default {
return this.file.type === 'folder'
},
isFile() {
return this.file.type === 'file'
return this.file.type !== 'folder' && this.file.type !== 'image'
},
isImage() {
return this.file.type === 'image'
}
},
filters: {
pluralize(word, amount) {
return amount > 1 ? word + 's' : word
}
},
}
</script>
<style scoped lang="scss">
@import "@assets/app.scss";
.file-item {
display: flex;
align-items: center;
padding: 8px 15px;
padding: 10px 15px;
@include transition(150ms);
cursor: pointer;
@@ -85,7 +79,7 @@ export default {
.item-size,
.item-length {
@include font-size(11);
font-weight: 100;
font-weight: 400;
color: $text-muted;
display: block;
}
@@ -107,6 +101,8 @@ export default {
.icon-item {
position: relative;
min-width: 40px;
text-align: center;
line-height: 0;
.file-icon {
@include font-size(35);
@@ -118,39 +114,32 @@ export default {
}
}
&.file {
.file-icon-text {
top: 40%;
@include font-size(9);
line-height: 1;
margin: 0 auto;
position: absolute;
text-align: center;
.file-icon-text {
top: 40%;
@include font-size(9);
margin: 0 auto;
position: absolute;
text-align: center;
left: 0;
right: 0;
color: $theme;
font-weight: 600;
user-select: none;
max-width: 20px;
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: 20px;
max-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&.image {
line-height: 0;
img {
object-fit: cover;
user-select: none;
max-width: 100%;
border-radius: 5px;
width: 36px;
height: 36px;
}
.image {
object-fit: cover;
user-select: none;
max-width: 100%;
border-radius: 5px;
width: 36px;
height: 36px;
}
}
}

View File

@@ -1,8 +1,8 @@
<template>
<div class="storage-size" v-if="app">
<div class="storage-info">
<span class="title">Storage</span>
<span class="size">{{ app.storage.used }} of {{ app.storage.capacity }} Used</span>
<span class="title">{{ $t('storage.title') }}</span>
<span class="size">{{ $t('storage.used', {used: app.storage.used, capacity: app.storage.capacity}) }}</span>
</div>
<ProgressBar :progress="app.storage.percentage" :class="{'is-exceeded': app.storage.percentage > 100}"/>
</div>
@@ -74,8 +74,13 @@
.size {
@include font-size(10);
}
}
}
.title {
@media (prefers-color-scheme: dark) {
.storage-size {
.storage-info .title {
color: $dark_mode_text_primary;
}
}

View File

@@ -12,8 +12,8 @@
<transition name="user-menu">
<div class="user-menu" v-if="isOpenedMenu">
<ul class="menu-options" id="menu-options-list" @click="closeMenu">
<li class="menu-option" @click="$goToView('user-settings')">Profile Settings</li>
<li class="menu-option" @click="$store.dispatch('logOut')">Log Out</li>
<li class="menu-option" @click="$goToView('user-settings')">{{ $t('context_menu.profile_settings') }}</li>
<li class="menu-option" @click="$store.dispatch('logOut')">{{ $t('context_menu.log_out') }}</li>
</ul>
</div>
</transition>
@@ -70,12 +70,14 @@
left: 0;
right: 0;
margin: 15px;
padding: 5px;
user-select: none;
border-radius: 8px;
display: flex;
align-items: center;
cursor: pointer;
@include transition(150ms);
background: darken($light_background, 3%);
&:active {
transform: scale(0.95);
@@ -103,6 +105,7 @@
color: $theme;
display: block;
margin-top: 2px;
font-weight: 600;
}
}
@@ -137,7 +140,7 @@
border-radius: 8px;
.menu-option {
font-weight: 600;
font-weight: 700;
@include font-size(15);
padding: 15px 30px;
cursor: pointer;
@@ -156,17 +159,15 @@
.user-headline {
position: relative;
margin-bottom: 40px;
background: transparent;
padding: 0;
}
}
@media (prefers-color-scheme: dark) {
#sidebar {
background: $dark_mode_background;
}
.user-headline {
background: transparent;
background: $dark_mode_background;
&:hover {
background: transparent;

View File

@@ -1,7 +1,7 @@
<template>
<div id="user-settings">
<PageHeader title="User Profile" />
<PageHeader :title="$t('profile.page_title')" />
<div class="content-page">
<div class="avatar-upload">
@@ -10,27 +10,27 @@
:avatar="app.user.avatar"
/>
<div class="info">
<span class="description">Change Your Profile Picture</span>
<span class="supported">Supported formats are .png, .jpg, .jpeg.</span>
<span class="description">{{ $t('profile.photo_description') }}</span>
<span class="supported">{{ $t('profile.photo_supported') }}</span>
</div>
</div>
<ValidationObserver ref="account" v-slot="{ invalid }" tag="form" class="form block-form">
<ThemeLabel>Profile Information</ThemeLabel>
<ThemeLabel>{{ $t('profile.profile_info') }}</ThemeLabel>
<div class="block-wrapper">
<label>Email:</label>
<label>{{ $t('page_registration.label_email') }}</label>
<div class="input-wrapper">
<input :value="app.user.email" placeholder="Type your E-mail" type="email" disabled/>
<input :value="app.user.email" :placeholder="$t('page_registration.placeholder_email')" type="email" disabled/>
</div>
</div>
<div class="block-wrapper">
<label>Full Name:</label>
<label>{{ $t('page_registration.label_name') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Full Name" rules="required"
v-slot="{ errors }">
<input @keyup="$updateText('/user/profile', 'name', name)" v-model="name"
placeholder="Type your full name" type="text"
:placeholder="$t('page_registration.placeholder_name')" type="text"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -40,23 +40,23 @@
<ValidationObserver ref="password" @submit.prevent="resetPassword" v-slot="{ invalid }" tag="form"
class="form block-form">
<ThemeLabel>Change Password</ThemeLabel>
<ThemeLabel>{{ $t('profile.change_pass') }}</ThemeLabel>
<div class="block-wrapper">
<label>Your Password:</label>
<label>{{ $t('page_create_password.label_new_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="New Password"
rules="required" v-slot="{ errors }">
<input v-model="newPassword" placeholder="New Password" type="password"
<input v-model="newPassword" :placeholder="$t('page_create_password.label_new_pass')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Repeat Your Password:</label>
<label>{{ $t('page_create_password.label_confirm_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Your Password"
rules="required" v-slot="{ errors }">
<input v-model="newPasswordConfirmation" placeholder="Confirm your new password" type="password"
<input v-model="newPasswordConfirmation" :placeholder="$t('page_create_password.label_confirm_pass')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -64,7 +64,7 @@
<div class="block-wrapper">
<ButtonBase type="submit" button-style="theme" class="confirm-form">
Store New Password
{{ $t('profile.store_pass') }}
</ButtonBase>
</div>
</ValidationObserver>
@@ -138,8 +138,8 @@
// Show error message
events.$emit('success:open', {
title: 'Your password was changed!',
message: 'So now, you have awesome new password.',
title: this.$t('popup_pass_changed.title'),
message: this.$t('popup_pass_changed.message'),
})
})
.catch(error => {

View File

@@ -19,9 +19,8 @@ const Helpers = {
axios.put(this.$store.getters.api + route, {name, value})
.catch(error => {
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
})
}, 300)
@@ -42,9 +41,8 @@ const Helpers = {
})
.catch(error => {
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
})
}
@@ -66,9 +64,8 @@ const Helpers = {
if (this.$store.getters.app.storage.percentage >= 100) {
events.$emit('alert:open', {
emoji: '😬😬😬',
title: 'Whooops, you exceed your storage limit :(',
message:
"Please contact your administrator to change your limit."
title: this.$t('popup_exceed_limit.title'),
message: this.$t('popup_exceed_limit.message')
})
return
@@ -117,18 +114,89 @@ const Helpers = {
events.$emit('alert:open', {
emoji: '😬😬😬',
title: 'Whooops, you exceed your storage limit :(',
message:
"Please contact your administrator to change your limit."
title: this.$t('popup_exceed_limit.title'),
message: this.$t('popup_exceed_limit.message')
})
} else {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
}
})
}
}
Vue.prototype.$uploadExternalFiles = async function(event, parent_id) {
// Prevent submit empty files
if (event.dataTransfer.items.length == 0) return
// Get files
const files = [...event.dataTransfer.items].map(item => item.getAsFile());
if (this.$store.getters.app.storage.percentage >= 100) {
events.$emit('alert:open', {
emoji: '😬😬😬',
title: this.$t('popup_exceed_limit.title'),
message: this.$t('popup_exceed_limit.message')
})
return
}
let fileCountSucceed = 1
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: files.length
})
for (var i = files.length - 1; i >= 0; i--) {
let formData = new FormData()
// Append data
formData.append('file', files[i])
// Append form data
formData.append('parent_id', parent_id)
// Upload data
await store.dispatch('uploadFiles', formData).then(() => {
// Progress file log
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: files.length
})
// Progress file log
store.commit('INCREASE_FOLDER_ITEM', parent_id)
// Uploading finished
if (files.length === fileCountSucceed) {
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
} else {
// Add uploaded file
fileCountSucceed++
}
}).catch(error => {
if (error.response.status == 423) {
events.$emit('alert:open', {
emoji: '😬😬😬',
title: this.$t('popup_exceed_limit.title'),
message: this.$t('popup_exceed_limit.message')
})
} else {
// Show error message
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
}
})
@@ -189,9 +257,8 @@ const Helpers = {
Vue.prototype.$isSomethingWrong = function() {
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
}
}

16
resources/js/i18n/index.js vendored Normal file
View File

@@ -0,0 +1,16 @@
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import en from './lang/en.json'
import sk from './lang/sk.json'
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: config.locale,
messages: Object.assign({
en, sk
}),
});
export default i18n;

View File

@@ -0,0 +1,165 @@
{
"routes": {
"create_new_password": "create-new-password"
},
"profile": {
"page_title": "User Profile",
"store_pass": "Store New Password",
"change_pass": "Change Password",
"profile_info": "Profile Information",
"photo_description": "Change Your Profile Picture",
"photo_supported": "Supported formats are .png, .jpg, .jpeg."
},
"page_registration": {
"title": "Create New Account",
"subtitle": "Please fill registration to create account:",
"label_email": "Email:",
"placeholder_email": "Type your E-mail",
"label_name": "Full Name:",
"placeholder_name": "Type your full name",
"label_pass": "Create password:",
"placeholder_pass": "Your new password",
"label_confirm_pass": "Confirm password:",
"placeholder_confirm_pass": "Confirm your new password",
"button_create_account": "Create Account",
"have_an_account": "Do you have an account?"
},
"page_create_password": {
"title": "Only One Step to Log In",
"subtitle": "Create your new password here:",
"button_update": "Update Password",
"label_email": "Email:",
"label_new_pass": "Your new password",
"label_confirm_pass": "Confirm new password"
},
"page_forgotten_password": {
"title": "Forgotten Password?",
"subtitle": "Get reset link with your email:",
"button_get_link": "Get Link",
"password_remember_text": "Remember your password?",
"password_remember_button": "Log In.",
"pass_sennded_title": "Thank you!",
"pass_sennded_subtitle": "We have e-mailed your password reset link!",
"pass_reseted_title": "Awesome!",
"pass_reseted_subtitle": "Your password was reset successfully.",
"pass_reseted_signin": "Sign In"
},
"page_sign_in": {
"title": "Are You {name}?",
"subtitle": "Confirm you by your password:",
"placeholder_password": "Type your password",
"button_log_in": "Log In",
"password_reset_text": "Forgotten your password?",
"password_reset_button": "Reset Password."
},
"page_login": {
"title": "Welcome Back!",
"subtitle": "Please type your email to log in:",
"placeholder_email": "Type your E-mail",
"button_next": "Next Step",
"registration_text": "Dont have an account?",
"registration_button": "Register account."
},
"uploading": {
"progress": "Uploading files {current}/{total}"
},
"inputs": {
"placeholder_search_files": "Search files…"
},
"messages": {
"nothing_to_preview": "There is nothing to preview.",
"nothing_was_found": "Nothing was found"
},
"locations": {
"home": "Home",
"trash": "Trash"
},
"file_detail": {
"created_at": "Created at",
"where": "Where",
"size": "Size"
},
"empty_page": {
"description": "Upload some files here easily via upload button",
"call_to_action": "Upload File",
"title": "There is Nothing"
},
"alerts": {
"error_confirm": "Thats horrible!",
"success_confirm": "Awesome!"
},
"validation_errors": {
"wrong_image": "You may have uploaded the wrong file, try again!",
"incorrect_password": "Sorry, you passed incorrect password :("
},
"pronouns": {
"of": "of"
},
"storage": {
"used": "{used} of {capacity} Used",
"title": "Storage"
},
"folder": {
"item_counts": "{count} Item | {count} Items",
"empty": "Empty"
},
"item_thumbnail": {
"original_location": "Original Location",
"deleted_at": "Deleted {time}"
},
"preview_type": {
"list": "List",
"grid": "Grid"
},
"context_menu": {
"remove_from_favourites": "Remove Favourite",
"add_to_favourites": "Add to Favourites",
"profile_settings": "Profile Settings",
"create_folder": "Create Folder",
"empty_trash": "Empty Trash",
"add_folder": "Add Folder",
"download": "Download",
"log_out": "Log Out",
"restore": "Restore",
"upload": "Upload",
"detail": "Detail",
"rename": "Rename",
"delete": "Delete",
"move": "Move"
},
"sidebar": {
"locations": "Locations",
"favourites": "Favourites",
"favourites_empty": "Drag here your favourite folder.",
"latest": "Last Uploads",
"latest_empty": "You don't have any latest uploads."
},
"popup_rename": {
"title": "Change your item name"
},
"popup_create_folder": {
"title": "Please enter your new folder name",
"folder_default_name": "New Folder"
},
"popup_move_item": {
"submit": "Move Item",
"title": "Move Item",
"cancel": "Cancel"
},
"popup_pass_changed": {
"title": "Your password was changed!",
"message": "So now, you have awesome new password."
},
"popup_trashed": {
"title": "Your trash was erased!",
"message": "So now, you have clear and empty trash."
},
"popup_error": {
"title": "Whooops, something went wrong!",
"message": "Something went wrong and we can't continue. Please contact us."
},
"popup_exceed_limit": {
"title": "Whooops, you exceed your storage limit :(",
"message": "Please contact your administrator to change your limit."
}
}

View File

@@ -0,0 +1,165 @@
{
"routes": {
"create_new_password": "vytvorit-nove-heslo"
},
"profile": {
"page_title": "Uživateľský profil",
"store_pass": "Uložiť nové heslo",
"change_pass": "Zmeniť heslo",
"profile_info": "Profil",
"photo_description": "Zmeň svoj avatar",
"photo_supported": "Podporované formáty sú .png, .jpg, .jpeg."
},
"page_registration": {
"title": "Vytvorenie nového účtu",
"subtitle": "Prosím, vyplňte formulár pre vytvorenie nového účtu:",
"label_email": "Email:",
"placeholder_email": "Napíš svoj E-mail",
"label_name": "Celé meno:",
"placeholder_name": "Napíš svoje celé meno",
"label_pass": "Vytvorte heslo:",
"placeholder_pass": "Vaše nové heslo",
"label_confirm_pass": "Potvrďte heslo:",
"placeholder_confirm_pass": "Potvrďte nové heslo",
"button_create_account": "Vytvoriť účet",
"have_an_account": "Máš už účet?"
},
"page_create_password": {
"title": "Iba jeden krok pre prihlásenie",
"subtitle": "Vytvorte si nové heslo tu:",
"button_update": "Aktualizovať heslo",
"label_email": "Email:",
"label_new_pass": "Vaše nové heslo",
"label_confirm_pass": "Potvrďte nové heslo"
},
"page_forgotten_password": {
"title": "Zabudnuté heslo?",
"subtitle": "Získajte resetovací link pre Váš účet:",
"button_get_link": "Získať link",
"password_remember_text": "Pamätáte si heslo?",
"password_remember_button": "Prihlásiť sa.",
"pass_sennded_title": "Ďakujeme!",
"pass_sennded_subtitle": "Práve sme Vám odoslali link na Váš email!",
"pass_reseted_title": "Skvelé!",
"pass_reseted_subtitle": "Tvoje heslo bolo obnovené úspešne.",
"pass_reseted_signin": "Prihlásiť sa"
},
"page_sign_in": {
"title": "Voláte sa {name}?",
"subtitle": "Potvrďte zadaním hesla:",
"placeholder_password": "Napíšte svoje heslo",
"button_log_in": "Prihlásiť sa",
"password_reset_text": "Zabudli ste heslo?",
"password_reset_button": "Resetovať heslo."
},
"page_login": {
"title": "Vitaj späť!",
"subtitle": "Prosím, vložte svoj email pre prihlásenie:",
"placeholder_email": "Napíšte svoj E-mail",
"button_next": "Ďalší krok",
"registration_text": "Ešte nemáte účet?",
"registration_button": "Vytvoriť účet."
},
"uploading": {
"progress": "Nahrávam súbory {current}/{total}"
},
"inputs": {
"placeholder_search_files": "Hľadajte súbory…"
},
"messages": {
"nothing_to_preview": "Tu nie je nič pre zobrazenie.",
"nothing_was_found": "Nič sa nenašlo"
},
"locations": {
"home": "Domov",
"trash": "Kôš"
},
"file_detail": {
"created_at": "Vytvorené",
"where": "Umiestnenie",
"size": "Veľkosť"
},
"empty_page": {
"description": "Nahrajte súbory jednoducho cez tlačidlo nahrať",
"call_to_action": "Nahrať súbory",
"title": "Tu nie je nič"
},
"alerts": {
"error_confirm": "To je hrozné!",
"success_confirm": "Skvelé!"
},
"validation_errors": {
"wrong_image": "Zrejme ste vložili zlý obrázok, skúste to znova!",
"incorrect_password": "Prepáč, vložili ste nesprávne heslo :("
},
"pronouns": {
"of": "z"
},
"storage": {
"used": "{used} z {capacity} Použité",
"title": "Úložisko"
},
"folder": {
"item_counts": "{count} Položka | {count} Položky",
"empty": "Prázdne"
},
"item_thumbnail": {
"original_location": "Pôvodné umiestnenie",
"deleted_at": "Vymazané {time}"
},
"preview_type": {
"list": "List",
"grid": "Mriežka"
},
"context_menu": {
"remove_from_favourites": "Vymazať obľúbené",
"add_to_favourites": "Pridať do obľúbených",
"profile_settings": "Nastavenia profilu",
"create_folder": "Vytvoriť priečinok",
"empty_trash": "Vyprázdniť kôš",
"add_folder": "Nový priečinok",
"download": "Stiahnúť",
"log_out": "Odhlásiť sa",
"restore": "Obnoviť",
"upload": "Nahrať",
"detail": "Detail",
"rename": "Premenovať",
"delete": "Vymazať",
"move": "Presunúť"
},
"sidebar": {
"locations": "Umiestnenie",
"favourites": "Obľúbené",
"favourites_empty": "Presuňte sem svoj obľúbený priečinok.",
"latest": "Posledne nahrané",
"latest_empty": "Nemáte žiadne nahrané súbory"
},
"popup_rename": {
"title": "Zmeňte názov položky"
},
"popup_create_folder": {
"title": "Prosím, vložte názov nového priečinka",
"folder_default_name": "Nový priečinok"
},
"popup_move_item": {
"submit": "Presunúť položku",
"title": "Presuňte položku",
"cancel": "Zrušiť"
},
"popup_pass_changed": {
"title": "Tvoje heslo bolo zmenené!",
"message": "Od teraz máte nové heslo."
},
"popup_trashed": {
"title": "Váš kôš bol vymazaný!",
"message": "Od teraz máte prázdny a čistý kôš"
},
"popup_error": {
"title": "Ups, niekde nastala chyba!",
"message": "Niečo sa stalo a nemôžme pokračovať. Prosím kontaktuj nás."
},
"popup_exceed_limit": {
"title": "Ups, presiahli ste limit úložiska",
"message": "Prosím, kontaktujte administrátora pre navyšenie limitu."
}
}

View File

@@ -1,12 +1,14 @@
require('./bootstrap');
import Vue from 'vue'
import i18n from './i18n/index.js'
import App from './App.vue'
import store from './store/index'
import Helpers from './helpers'
import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import axios from 'axios'
import {
faFileAudio,
faFileVideo,
faSyncAlt,
faShare,
faHome,
@@ -29,9 +31,12 @@ import {
faTrashAlt,
faHdd,
faEllipsisH,
faPencilAlt,
} from '@fortawesome/free-solid-svg-icons'
library.add(
faFileAudio,
faFileVideo,
faHdd,
faSyncAlt,
faShare,
@@ -54,6 +59,7 @@ library.add(
faTimes,
faSort,
faEllipsisH,
faPencilAlt,
)
Vue.component('FontAwesomeIcon', FontAwesomeIcon)
@@ -62,6 +68,7 @@ Vue.use(Helpers)
Vue.config.productionTip = false
var vueFileManager = new Vue({
i18n,
store,
data: {
config,

View File

@@ -1,6 +1,3 @@
import axios from 'axios'
import { events } from '@/bus'
const defaultState = {
currentView: 'files',
appSize: undefined,

View File

@@ -1,8 +1,9 @@
import axios from 'axios'
import {events} from '@/bus'
import i18n from '@/i18n/index.js'
const defaultState = {
fileInfoPanelVisible: localStorage.getItem('file_info_visibility') == 'false' || false,
fileInfoPanelVisible: localStorage.getItem('file_info_visibility') == 'true' || false,
preview_type: localStorage.getItem('preview_type') || 'list',
uploadingFilesCount: undefined,
fileInfoDetail: undefined,
@@ -62,9 +63,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -100,9 +100,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -112,7 +111,7 @@ const actions = {
axios
.delete(context.getters.api + '/empty-trash')
.then(response => {
.then(() => {
context.commit('LOADING_STATE', false)
events.$emit('scrollTop')
@@ -121,16 +120,15 @@ const actions = {
// Show error message
events.$emit('success:open', {
title: 'Your trash was erased!',
message: 'So now, you have clear and empty trash.',
title: i18n.t('popup_trashed.title'),
message: i18n.t('popup_trashed.message'),
})
})
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -150,9 +148,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -169,9 +166,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -197,9 +193,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -225,9 +220,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -271,6 +265,8 @@ const actions = {
})
},
changeItemName: (context, data) => {
if (data.type === 'folder') context.commit('UPDATE_NAME_IN_FAVOURITES', data)
axios
@@ -281,9 +277,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -303,9 +298,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -346,9 +340,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -370,9 +363,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
}
@@ -395,25 +387,16 @@ const mutations = {
state.browseHistory.pop()
},
CHANGE_ITEM_NAME(state, updatedFile) {
// Rename filename in file info detail
if (
state.fileInfoDetail &&
state.fileInfoDetail.unique_id == updatedFile.unique_id
) {
if (state.fileInfoDetail && state.fileInfoDetail.unique_id == updatedFile.unique_id) {
state.fileInfoDetail = updatedFile
}
// Get file
const file = state.data.find(
el => el.unique_id == updatedFile.unique_id
)
file.file_url = updatedFile.file_url
file.thumbnail = updatedFile.thumbnail
if (this._vm.$isMobile()) {
file.name = updatedFile.name
}
// Rename item name in data view
state.data.find(item => {
if (item.unique_id == updatedFile.unique_id) item.name = updatedFile.name
})
},
CLEAR_FILEINFO_DETAIL(state) {
state.fileInfoDetail = undefined

View File

@@ -1,5 +1,6 @@
import axios from 'axios'
import {events} from '@/bus'
import i18n from '@/i18n/index.js'
const defaultState = {
authorized: undefined,
@@ -41,9 +42,8 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
@@ -57,17 +57,41 @@ const actions = {
.catch(() => {
// Show error message
events.$emit('alert:open', {
title: 'Whooops, something went wrong :(',
message:
"Something went wrong and we can't continue. Please contact us."
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
},
getFolderTree: (context) => {
return new Promise((resolve, reject) => {
axios
.get(context.getters.api + '/folder-tree')
.then(response => {
resolve(response)
context.commit('UPDATE_FOLDER_TREE', response.data)
})
.catch((error) => {
reject(error)
// Show error message
events.$emit('alert:open', {
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
})
})
},
}
const mutations = {
RETRIEVE_APP_DATA(state, app) {
state.app = app
},
UPDATE_FOLDER_TREE(state, tree) {
state.app.folders = tree
},
SET_AUTHORIZED(state, data) {
state.authorized = data
},

View File

@@ -1,19 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Previous',
'next' => 'Next &raquo;',
];

View File

@@ -0,0 +1,7 @@
<?php
return [
'user_not_fount' => 'We can\'t find a user with that e-mail address.',
'home' => 'Home',
'time' => '%d. %B. %Y at %H:%M',
];

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'Prihlasovacie údaje nie sú správne.',
'throttle' => 'Prekročený limit pokusov. Skúste znovu o :seconds sekúnd.',
];

View File

@@ -0,0 +1,20 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'reset' => 'Heslo bolo zmenené!',
'sent' => 'Pripomienka k zmene hesla bola odoslaná!',
'throttled' => 'Pred ďalším pokusom chvíľu počkajte.',
'token' => 'Klúč pre obnovu hesla je neplatný.',
'user' => 'Nepodarilo sa nájsť používateľa s touto e-mailovou adresou.',
];

View File

@@ -0,0 +1,150 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages.
|
*/
'accepted' => ':Attribute musí byť akceptovaný.',
'active_url' => ':Attribute má neplatnú URL adresu.',
'after' => ':Attribute musí byť dátum po :date.',
'after_or_equal' => ':Attribute musí byť dátum po alebo presne :date.',
'alpha' => ':Attribute môže obsahovať len písmená.',
'alpha_dash' => ':Attribute môže obsahovať len písmená, čísla a pomlčky.',
'alpha_num' => ':Attribute môže obsahovať len písmená, čísla.',
'array' => ':Attribute musí byť pole.',
'before' => ':Attribute musí byť dátum pred :date.',
'before_or_equal' => ':Attribute musí byť dátum pred alebo presne :date.',
'between' => [
'numeric' => ':Attribute musí mať rozsah :min - :max.',
'file' => ':Attribute musí mať rozsah :min - :max kilobajtov.',
'string' => ':Attribute musí mať rozsah :min - :max znakov.',
'array' => ':Attribute musí mať rozsah :min - :max prvkov.',
],
'boolean' => ':Attribute musí byť pravda alebo nepravda.',
'confirmed' => ':Attribute konfirmácia sa nezhoduje.',
'date' => ':Attribute má neplatný dátum.',
'date_equals' => ':Attribute musí byť dátum rovnajúci sa :date.',
'date_format' => ':Attribute sa nezhoduje s formátom :format.',
'different' => ':Attribute a :other musia byť odlišné.',
'digits' => ':Attribute musí mať :digits číslic.',
'digits_between' => ':Attribute musí mať rozsah :min až :max číslic.',
'dimensions' => ':Attribute má neplatné rozmery obrázku.',
'distinct' => ':Attribute je duplicitný.',
'email' => ':Attribute má neplatný formát.',
'ends_with' => ':attribute musí obsahovať jednú z týchto hodnôt: :values.',
'exists' => 'označený :attribute je neplatný.',
'file' => ':Attribute musí byť súbor.',
'filled' => ':Attribute je požadované.',
'gt' => [
'numeric' => 'Hodnota :attribute musí byť väčšia ako :value.',
'file' => ':Attribute musí mať viac kilobajtov ako :value.',
'string' => ':Attribute musí mať viac znakov ako :value.',
'array' => ':Attribute musí mať viac prvkov ako :value.',
],
'gte' => [
'numeric' => 'Hodnota :attribute musí byť väčšia alebo rovná ako :value.',
'file' => ':Attribute musí mať rovnaký alebo väčší počet kilobajtov ako :value.',
'string' => ':Attribute musí mať rovnaký alebo väčší počet znakov ako :value.',
'array' => ':Attribute musí mať rovnaký alebo väčší počet prvkov ako :value.',
],
'image' => ':Attribute musí byť obrázok.',
'in' => 'označený :attribute je neplatný.',
'in_array' => ':Attribute sa nenachádza v :other.',
'integer' => ':Attribute musí byť celé číslo.',
'ip' => ':Attribute musí byť platná IP adresa.',
'ipv4' => ':Attribute musí byť platná IPv4 adresa.',
'ipv6' => ':Attribute musí byť platná IPv6 adresa.',
'json' => ':Attribute musí byť platný JSON reťazec.',
'lt' => [
'numeric' => 'Hodnota :attribute musí byť menšia ako :value.',
'file' => ':Attribute musí mať menej kilobajtov ako :value.',
'string' => ':Attribute musí mať menej znakov ako :value.',
'array' => ':Attribute musí mať menej prvkov ako :value.',
],
'lte' => [
'numeric' => 'Hodnota :attribute musí byť menšia alebo rovná ako :value.',
'file' => ':Attribute musí mať rovnaký alebo menší počet kilobajtov ako :value.',
'string' => ':Attribute musí mať rovnaký alebo menší počet znakov ako :value.',
'array' => ':Attribute musí mať rovnaký alebo menší počet prvkov ako :value.',
],
'max' => [
'numeric' => ':Attribute nemôže byť väčší ako :max.',
'file' => ':Attribute nemôže byť väčší ako :max kilobajtov.',
'string' => ':Attribute nemôže byť väčší ako :max znakov.',
'array' => ':Attribute nemôže mať viac ako :max prvkov.',
],
'mimes' => ':Attribute musí byť súbor s koncovkou: :values.',
'mimetypes' => ':Attribute musí byť súbor s koncovkou: :values.',
'min' => [
'numeric' => ':Attribute musí mať aspoň :min.',
'file' => ':Attribute musí mať aspoň :min kilobajtov.',
'string' => ':Attribute musí mať aspoň :min znakov.',
'array' => ':Attribute musí mať aspoň :min prvkov.',
],
'not_in' => 'označený :attribute je neplatný.',
'not_regex' => ':Attribute má neplatný formát.',
'numeric' => ':Attribute musí byť číslo.',
'password' => 'Heslo nie je správne',
'present' => ':Attribute musí byť odoslaný.',
'regex' => ':Attribute má neplatný formát.',
'required' => ':Attribute je požadované.',
'required_if' => ':Attribute je požadované keď :other je :value.',
'required_unless' => ':Attribute je požadované, okrem prípadu keď :other je v :values.',
'required_with' => ':Attribute je požadované keď :values je prítomné.',
'required_with_all' => ':Attribute je požadované ak :values je nastavené.',
'required_without' => ':Attribute je požadované keď :values nie je prítomné.',
'required_without_all' => ':Attribute je požadované ak žiadne z :values nie je nastavené.',
'same' => ':Attribute a :other sa musia zhodovať.',
'size' => [
'numeric' => ':Attribute musí byť :size.',
'file' => ':Attribute musí mať :size kilobajtov.',
'string' => ':Attribute musí mať :size znakov.',
'array' => ':Attribute musí obsahovať :size prvkov.',
],
'starts_with' => ':Attribute musí začínať niektorou z hodnôt: :values',
'string' => ':Attribute musí byť reťazec znakov.',
'timezone' => ':Attribute musí byť platné časové pásmo.',
'unique' => ':Attribute už existuje.',
'uploaded' => 'Nepodarilo sa nahrať :attribute.',
'url' => ':Attribute musí mať formát URL.',
'uuid' => ':Attribute musí byť platné UUID.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [
],
];

View File

@@ -0,0 +1,7 @@
<?php
return [
'user_not_fount' => 'Uživateľ s touto emailovou adresou sa nenašiel.',
'home' => 'Domov',
'time' => '%d. %B. %Y o %H:%M',
];

View File

@@ -1,5 +1,5 @@
// Fonts
@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');
// Variables
@import 'vue-file-manager/_variables';

View File

@@ -1,18 +1,23 @@
// Colors
$text: #35495d;
$text-muted: lighten($text, 25%);
$text: #1b2539;
$text-muted: #667b90;
$border: #F8F8FC;
$light_mode_border: rgba(0, 0, 0, 0.02);
$theme: #00BC7E;
$danger: #d22323;
$light_text: #A4ADB6;
$light_background: #f6f6f6;
$dark_background: #EBEBEB;
$shadow: 0 7px 25px 1px rgba(0, 0, 0, 0.12);
$light_mode_popup_shadow: 0 10px 50px rgba(0, 0, 0, .10);
$light_mode_vignette: rgba(255, 255, 255, 0.80);
// Dark Mode
$dark_mode_vignette: rgba(0, 0, 0, 0.3);
$dark_mode_background: #1a1f25;
$dark_mode_foreground: #202733;
$dark_mode_foreground: #1c222d;
$dark_mode_text_primary: #B8C4D0;
$dark_mode_text_secondary: #6A8BAD;
$dark_mode_text_secondary: #667b90;
$dark_mode_vignette: rgba(22, 23, 27, 0.70);
$dark_mode_popup_shadow: 0 10px 30px rgba(0, 0, 0, .3);
$dark_mode_border_color: rgba(255, 255, 255, 0.02);

View File

@@ -6,16 +6,26 @@
<meta name="description"
content="Manage your folders and files with Vue File Manager client powered by Laravel API endpoint.">
<title>VueFileManager | Manage your folders and files with Vue File Manager client powered by Laravel API endpoint.</title>
<title>VueFileManager | Make your own Private Cloud with VueFileManager client powered by Laravel and Vue</title>
<link rel="icon" href="{{ asset('favicon.ico') }}">
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="white">
<meta name="apple-mobile-web-app-title" content="{{ config('vuefilemanager.app_name') }}">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="{{ asset('assets/images/app-icon.png') }}">
<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="address=no">
</head>
<body>
<div id="app"></div>
<script>
let config = {
locale: '{{ \Illuminate\Support\Facades\App::getLocale() }}',
app_name: '{{ config('vuefilemanager.app_name') }}',
app_logo: '{{ asset(config('vuefilemanager.app_logo')) }}',
api: '{{ url('/api') }}',
hasAuthCookie: {{ Cookie::has('token') ? 1 : 0 }},
userRegistration: {{ config('vuefilemanager.registration') ? 1 : 0 }},

View File

@@ -56,6 +56,7 @@ Route::group(['middleware' => ['auth:api', 'auth.cookie']], function () {
Route::post('/rename-item', 'FileManagerController@rename_item');
Route::post('/remove-item', 'FileManagerController@delete_item');
Route::post('/upload-file', 'FileManagerController@upload_item');
Route::get('/folder-tree', 'UserAccountController@folder_tree');
Route::post('/move-item', 'FileManagerController@move_item');
Route::get('/search', 'FileManagerController@search');
Route::get('/trash', 'FileManagerController@trash');

View File

@@ -1,2 +0,0 @@
*
!.gitignore

4
webpack.mix.js vendored
View File

@@ -15,7 +15,6 @@ mix.js('resources/js/main.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css', {
implementation: require('node-sass')
})
.version()
.webpackConfig({
resolve: {
alias: {
@@ -23,4 +22,5 @@ mix.js('resources/js/main.js', 'public/js')
"@": path.resolve(__dirname, "resources/js"),
}
},
}).disableNotifications();
})
.disableNotifications();