瀏覽代碼

install tinymce (editor) for panel

Azam Rezayi 4 年之前
父節點
當前提交
c760530ad1
共有 29 個文件被更改,包括 2182 次插入5 次删除
  1. 1 0
      composer.json
  2. 146 1
      composer.lock
  3. 3 2
      config/app.php
  4. 167 0
      config/lfm.php
  5. 1 1
      packages/product/src/views/product/create.blade.php
  6. 8 0
      public/vendor/laravel-filemanager/css/cropper.min.css
  7. 532 0
      public/vendor/laravel-filemanager/css/dropzone.min.css
  8. 387 0
      public/vendor/laravel-filemanager/css/lfm.css
  9. 8 0
      public/vendor/laravel-filemanager/css/mime-icons.min.css
  10. 0 0
      public/vendor/laravel-filemanager/files/.gitkeep
  11. 二進制
      public/vendor/laravel-filemanager/files/adobe.pdf
  12. 二進制
      public/vendor/laravel-filemanager/files/folder-1/sleeping-dog.jpg
  13. 二進制
      public/vendor/laravel-filemanager/files/word.docx
  14. 0 0
      public/vendor/laravel-filemanager/images/.gitkeep
  15. 二進制
      public/vendor/laravel-filemanager/images/test-folder/sleeping-dog.jpg
  16. 二進制
      public/vendor/laravel-filemanager/images/test-folder/thumbs/sleeping-dog.jpg
  17. 二進制
      public/vendor/laravel-filemanager/img/152px color.png
  18. 二進制
      public/vendor/laravel-filemanager/img/72px color.png
  19. 二進制
      public/vendor/laravel-filemanager/img/92px color.png
  20. 二進制
      public/vendor/laravel-filemanager/img/Logomark color.png
  21. 二進制
      public/vendor/laravel-filemanager/img/folder.png
  22. 33 0
      public/vendor/laravel-filemanager/img/loader.svg
  23. 9 0
      public/vendor/laravel-filemanager/js/cropper.min.js
  24. 0 0
      public/vendor/laravel-filemanager/js/dropzone.min.js
  25. 812 0
      public/vendor/laravel-filemanager/js/script.js
  26. 36 0
      public/vendor/laravel-filemanager/js/stand-alone-button.js
  27. 33 0
      resources/js/panel/panel.js
  28. 3 1
      resources/views/panel/layouts/app.blade.php
  29. 3 0
      routes/panel/web.php

+ 1 - 0
composer.json

@@ -20,6 +20,7 @@
         "league/flysystem-cached-adapter": "~1.0",
         "morilog/jalali": "^3.1",
         "santigarcor/laratrust": "^6.0",
+        "unisharp/laravel-filemanager": "^2.1",
         "uxweb/sweet-alert": "^2.0",
         "va/cutlet-recaptcha": "^1.1"
     },

+ 146 - 1
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "751173416fac3566f8a8b1fdc34b47c1",
+    "content-hash": "8434a457d428825aacf1422269cdd227",
     "packages": [
         {
             "name": "asm89/stack-cors",
@@ -928,6 +928,76 @@
             "time": "2019-07-01T23:21:34+00:00"
         },
         {
+            "name": "intervention/image",
+            "version": "2.5.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Intervention/image.git",
+                "reference": "abbf18d5ab8367f96b3205ca3c89fb2fa598c69e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Intervention/image/zipball/abbf18d5ab8367f96b3205ca3c89fb2fa598c69e",
+                "reference": "abbf18d5ab8367f96b3205ca3c89fb2fa598c69e",
+                "shasum": ""
+            },
+            "require": {
+                "ext-fileinfo": "*",
+                "guzzlehttp/psr7": "~1.1",
+                "php": ">=5.4.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "~0.9.2",
+                "phpunit/phpunit": "^4.8 || ^5.7"
+            },
+            "suggest": {
+                "ext-gd": "to use GD library based image processing.",
+                "ext-imagick": "to use Imagick based image processing.",
+                "intervention/imagecache": "Caching extension for the Intervention Image library"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.4-dev"
+                },
+                "laravel": {
+                    "providers": [
+                        "Intervention\\Image\\ImageServiceProvider"
+                    ],
+                    "aliases": {
+                        "Image": "Intervention\\Image\\Facades\\Image"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Intervention\\Image\\": "src/Intervention/Image"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Oliver Vogel",
+                    "email": "oliver@olivervogel.com",
+                    "homepage": "http://olivervogel.com/"
+                }
+            ],
+            "description": "Image handling and manipulation library with support for Laravel integration",
+            "homepage": "http://image.intervention.io/",
+            "keywords": [
+                "gd",
+                "image",
+                "imagick",
+                "laravel",
+                "thumbnail",
+                "watermark"
+            ],
+            "time": "2019-11-02T09:15:47+00:00"
+        },
+        {
             "name": "kkszymanowski/traitor",
             "version": "0.2.5",
             "source": {
@@ -3859,6 +3929,81 @@
             "time": "2019-10-24T08:53:34+00:00"
         },
         {
+            "name": "unisharp/laravel-filemanager",
+            "version": "v2.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/UniSharp/laravel-filemanager.git",
+                "reference": "a2c390b1414fa35457fc5c6d01068dcf6dac7cd2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/UniSharp/laravel-filemanager/zipball/a2c390b1414fa35457fc5c6d01068dcf6dac7cd2",
+                "reference": "a2c390b1414fa35457fc5c6d01068dcf6dac7cd2",
+                "shasum": ""
+            },
+            "require": {
+                "ext-exif": "*",
+                "ext-fileinfo": "*",
+                "illuminate/config": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0",
+                "illuminate/container": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0",
+                "illuminate/filesystem": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0",
+                "illuminate/http": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0",
+                "illuminate/support": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0",
+                "intervention/image": "2.*",
+                "php": ">=7.2.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^0.9.9",
+                "phpunit/phpunit": "^6.2",
+                "squizlabs/php_codesniffer": "^3.1"
+            },
+            "suggest": {
+                "ext-gd": "to use GD library based image processing.",
+                "ext-imagick": "to use Imagick based image processing."
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "UniSharp\\LaravelFilemanager\\LaravelFilemanagerServiceProvider"
+                    ],
+                    "aliases": []
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "UniSharp\\LaravelFilemanager\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Trevor Sawler",
+                    "email": "trevor.sawler@gmail.com"
+                },
+                {
+                    "name": "UniSharp Ltd.",
+                    "email": "opensource@unisharp.com"
+                }
+            ],
+            "description": "A file upload/editor intended for use with Laravel 5 to 6 and CKEditor / TinyMCE",
+            "keywords": [
+                "CKEditor",
+                "file",
+                "filemanager",
+                "image",
+                "laravel",
+                "manager",
+                "tinymce",
+                "upload"
+            ],
+            "time": "2020-05-10T10:10:07+00:00"
+        },
+        {
             "name": "uxweb/sweet-alert",
             "version": "v2.0.3",
             "source": {

+ 3 - 2
config/app.php

@@ -171,6 +171,8 @@ return [
          Packages\Product\ProductServiceProvider::class,
 
         App\Providers\HelpersServiceProvider::class,
+        UniSharp\LaravelFilemanager\LaravelFilemanagerServiceProvider::class,
+        Intervention\Image\ImageServiceProvider::class,
 
         /*
          * Application Service Providers...
@@ -234,8 +236,7 @@ return [
         'URL' => Illuminate\Support\Facades\URL::class,
         'Validator' => Illuminate\Support\Facades\Validator::class,
         'View' => Illuminate\Support\Facades\View::class,
-//        'jDate' => Morilog\Jalali\Facades\jDate::class,
-//        'jDateTime' => Morilog\Jalali\Facades\jDateTime::class,
+        'Image' => Intervention\Image\Facades\Image::class,
 
 
     ],

+ 167 - 0
config/lfm.php

@@ -0,0 +1,167 @@
+<?php
+
+/*
+|--------------------------------------------------------------------------
+| Documentation for this config :
+|--------------------------------------------------------------------------
+| online  => http://unisharp.github.io/laravel-filemanager/config
+| offline => vendor/unisharp/laravel-filemanager/docs/config.md
+ */
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | Routing
+    |--------------------------------------------------------------------------
+     */
+
+    'use_package_routes'       => true,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Shared folder / Private folder
+    |--------------------------------------------------------------------------
+    |
+    | If both options are set to false, then shared folder will be activated.
+    |
+     */
+
+    'allow_private_folder'     => true,
+
+    // Flexible way to customize client folders accessibility
+    // If you want to customize client folders, publish tag="lfm_handler"
+    // Then you can rewrite userField function in App\Handler\ConfigHandler class
+    // And set 'user_field' to App\Handler\ConfigHandler::class
+    // Ex: The private folder of user will be named as the user id.
+    'private_folder_name'      => UniSharp\LaravelFilemanager\Handlers\ConfigHandler::class,
+
+    'allow_shared_folder'      => true,
+
+    'shared_folder_name'       => 'shares',
+
+    /*
+    |--------------------------------------------------------------------------
+    | Folder Names
+    |--------------------------------------------------------------------------
+     */
+
+    'folder_categories'        => [
+        'file'  => [
+            'folder_name'  => 'files',
+            'startup_view' => 'grid',
+            'max_size'     => 50000, // size in KB
+            'valid_mime'   => [
+                'image/jpeg',
+                'image/pjpeg',
+                'image/png',
+                'image/gif',
+                'image/svg+xml',
+            ],
+        ],
+        'image' => [
+            'folder_name'  => 'photos',
+            'startup_view' => 'list',
+            'max_size'     => 50000, // size in KB
+            'valid_mime'   => [
+                'image/jpeg',
+                'image/pjpeg',
+                'image/png',
+                'image/gif',
+                'image/svg+xml',
+                'application/pdf',
+                'text/plain',
+            ],
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Pagination
+    |--------------------------------------------------------------------------
+     */
+
+    'paginator' => [
+        'perPage' => 30,
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Upload / Validation
+    |--------------------------------------------------------------------------
+     */
+
+    'disk'                     => 'public',
+
+    'rename_file'              => false,
+
+    'alphanumeric_filename'    => false,
+
+    'alphanumeric_directory'   => false,
+
+    'should_validate_size'     => false,
+
+    'should_validate_mime'     => false,
+
+    // behavior on files with identical name
+    // setting it to true cause old file replace with new one
+    // setting it to false show `error-file-exist` error and stop upload
+    'over_write_on_duplicate'  => false,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Thumbnail
+    |--------------------------------------------------------------------------
+     */
+
+    // If true, image thumbnails would be created during upload
+    'should_create_thumbnails' => true,
+
+    'thumb_folder_name'        => 'thumbs',
+
+    // Create thumbnails automatically only for listed types.
+    'raster_mimetypes'         => [
+        'image/jpeg',
+        'image/pjpeg',
+        'image/png',
+    ],
+
+    'thumb_img_width'          => 200, // px
+
+    'thumb_img_height'         => 200, // px
+
+    /*
+    |--------------------------------------------------------------------------
+    | File Extension Information
+    |--------------------------------------------------------------------------
+     */
+
+    'file_type_array'          => [
+        'pdf'  => 'Adobe Acrobat',
+        'doc'  => 'Microsoft Word',
+        'docx' => 'Microsoft Word',
+        'xls'  => 'Microsoft Excel',
+        'xlsx' => 'Microsoft Excel',
+        'zip'  => 'Archive',
+        'gif'  => 'GIF Image',
+        'jpg'  => 'JPEG Image',
+        'jpeg' => 'JPEG Image',
+        'png'  => 'PNG Image',
+        'ppt'  => 'Microsoft PowerPoint',
+        'pptx' => 'Microsoft PowerPoint',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | php.ini override
+    |--------------------------------------------------------------------------
+    |
+    | These values override your php.ini settings before uploading files
+    | Set these to false to ingnore and apply your php.ini settings
+    |
+    | Please note that the 'upload_max_filesize' & 'post_max_size'
+    | directives are not supported.
+     */
+    'php_ini_overrides'        => [
+        'memory_limit' => '256M',
+    ],
+];

+ 1 - 1
packages/product/src/views/product/create.blade.php

@@ -158,7 +158,7 @@
                                         <label for="discription">{{ __('product.discription') }}</label></label><i
                                             class="required">&nbsp; *</i>
                                         <textarea id="editor" type="text"
-                                                  class="form-control ClassicEditor @error('discription') is-invalid @enderror"
+                                                  class="form-control ClassicEditor  @error('discription') is-invalid @enderror"
                                                   name="discription"
 
                                                   autocomplete="discription"

文件差異過大導致無法顯示
+ 8 - 0
public/vendor/laravel-filemanager/css/cropper.min.css


+ 532 - 0
public/vendor/laravel-filemanager/css/dropzone.min.css

@@ -0,0 +1,532 @@
+@-webkit-keyframes passing-through {
+    0% {
+        opacity: 0;
+        -webkit-transform: translateY(40px);
+        -moz-transform: translateY(40px);
+        -ms-transform: translateY(40px);
+        -o-transform: translateY(40px);
+        transform: translateY(40px)
+    }
+
+    30%, 70% {
+        opacity: 1;
+        -webkit-transform: translateY(0px);
+        -moz-transform: translateY(0px);
+        -ms-transform: translateY(0px);
+        -o-transform: translateY(0px);
+        transform: translateY(0px)
+    }
+
+    100% {
+        opacity: 0;
+        -webkit-transform: translateY(-40px);
+        -moz-transform: translateY(-40px);
+        -ms-transform: translateY(-40px);
+        -o-transform: translateY(-40px);
+        transform: translateY(-40px)
+    }
+
+}
+
+@-moz-keyframes passing-through {
+    0% {
+        opacity: 0;
+        -webkit-transform: translateY(40px);
+        -moz-transform: translateY(40px);
+        -ms-transform: translateY(40px);
+        -o-transform: translateY(40px);
+        transform: translateY(40px)
+    }
+
+    30%, 70% {
+        opacity: 1;
+        -webkit-transform: translateY(0px);
+        -moz-transform: translateY(0px);
+        -ms-transform: translateY(0px);
+        -o-transform: translateY(0px);
+        transform: translateY(0px)
+    }
+
+    100% {
+        opacity: 0;
+        -webkit-transform: translateY(-40px);
+        -moz-transform: translateY(-40px);
+        -ms-transform: translateY(-40px);
+        -o-transform: translateY(-40px);
+        transform: translateY(-40px)
+    }
+
+}
+
+@keyframes passing-through {
+    0% {
+        opacity: 0;
+        -webkit-transform: translateY(40px);
+        -moz-transform: translateY(40px);
+        -ms-transform: translateY(40px);
+        -o-transform: translateY(40px);
+        transform: translateY(40px)
+    }
+
+    30%, 70% {
+        opacity: 1;
+        -webkit-transform: translateY(0px);
+        -moz-transform: translateY(0px);
+        -ms-transform: translateY(0px);
+        -o-transform: translateY(0px);
+        transform: translateY(0px)
+    }
+
+    100% {
+        opacity: 0;
+        -webkit-transform: translateY(-40px);
+        -moz-transform: translateY(-40px);
+        -ms-transform: translateY(-40px);
+        -o-transform: translateY(-40px);
+        transform: translateY(-40px)
+    }
+
+}
+
+@-webkit-keyframes slide-in {
+    0% {
+        opacity: 0;
+        -webkit-transform: translateY(40px);
+        -moz-transform: translateY(40px);
+        -ms-transform: translateY(40px);
+        -o-transform: translateY(40px);
+        transform: translateY(40px)
+    }
+
+    30% {
+        opacity: 1;
+        -webkit-transform: translateY(0px);
+        -moz-transform: translateY(0px);
+        -ms-transform: translateY(0px);
+        -o-transform: translateY(0px);
+        transform: translateY(0px)
+    }
+
+}
+
+@-moz-keyframes slide-in {
+    0% {
+        opacity: 0;
+        -webkit-transform: translateY(40px);
+        -moz-transform: translateY(40px);
+        -ms-transform: translateY(40px);
+        -o-transform: translateY(40px);
+        transform: translateY(40px)
+    }
+
+    30% {
+        opacity: 1;
+        -webkit-transform: translateY(0px);
+        -moz-transform: translateY(0px);
+        -ms-transform: translateY(0px);
+        -o-transform: translateY(0px);
+        transform: translateY(0px)
+    }
+
+}
+
+@keyframes slide-in {
+    0% {
+        opacity: 0;
+        -webkit-transform: translateY(40px);
+        -moz-transform: translateY(40px);
+        -ms-transform: translateY(40px);
+        -o-transform: translateY(40px);
+        transform: translateY(40px)
+    }
+
+    30% {
+        opacity: 1;
+        -webkit-transform: translateY(0px);
+        -moz-transform: translateY(0px);
+        -ms-transform: translateY(0px);
+        -o-transform: translateY(0px);
+        transform: translateY(0px)
+    }
+
+}
+
+@-webkit-keyframes pulse {
+    0% {
+        -webkit-transform: scale(1);
+        -moz-transform: scale(1);
+        -ms-transform: scale(1);
+        -o-transform: scale(1);
+        transform: scale(1)
+    }
+
+    10% {
+        -webkit-transform: scale(1.1);
+        -moz-transform: scale(1.1);
+        -ms-transform: scale(1.1);
+        -o-transform: scale(1.1);
+        transform: scale(1.1)
+    }
+
+    20% {
+        -webkit-transform: scale(1);
+        -moz-transform: scale(1);
+        -ms-transform: scale(1);
+        -o-transform: scale(1);
+        transform: scale(1)
+    }
+
+}
+
+@-moz-keyframes pulse {
+    0% {
+        -webkit-transform: scale(1);
+        -moz-transform: scale(1);
+        -ms-transform: scale(1);
+        -o-transform: scale(1);
+        transform: scale(1)
+    }
+
+    10% {
+        -webkit-transform: scale(1.1);
+        -moz-transform: scale(1.1);
+        -ms-transform: scale(1.1);
+        -o-transform: scale(1.1);
+        transform: scale(1.1)
+    }
+
+    20% {
+        -webkit-transform: scale(1);
+        -moz-transform: scale(1);
+        -ms-transform: scale(1);
+        -o-transform: scale(1);
+        transform: scale(1)
+    }
+
+}
+
+@keyframes pulse {
+    0% {
+        -webkit-transform: scale(1);
+        -moz-transform: scale(1);
+        -ms-transform: scale(1);
+        -o-transform: scale(1);
+        transform: scale(1)
+    }
+
+    10% {
+        -webkit-transform: scale(1.1);
+        -moz-transform: scale(1.1);
+        -ms-transform: scale(1.1);
+        -o-transform: scale(1.1);
+        transform: scale(1.1)
+    }
+
+    20% {
+        -webkit-transform: scale(1);
+        -moz-transform: scale(1);
+        -ms-transform: scale(1);
+        -o-transform: scale(1);
+        transform: scale(1)
+    }
+
+}
+
+.dropzone, .dropzone * {
+    box-sizing: border-box
+}
+
+.dropzone {
+    min-height: 150px;
+    border: 2px solid rgba(0, 0, 0, 0.3);
+    background: white;
+    padding: 20px 20px
+}
+
+.dropzone.dz-clickable {
+    cursor: pointer
+}
+
+.dropzone.dz-clickable * {
+    cursor: default
+}
+
+.dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
+    cursor: pointer
+}
+
+.dropzone.dz-started .dz-message {
+    display: none
+}
+
+.dropzone.dz-drag-hover {
+    border-style: solid
+}
+
+.dropzone.dz-drag-hover .dz-message {
+    opacity: 0.5
+}
+
+.dropzone .dz-message {
+    text-align: center;
+    margin: 2em 0
+}
+
+.dropzone .dz-preview {
+    position: relative;
+    display: inline-block;
+    vertical-align: top;
+    margin: 16px;
+    min-height: 100px
+}
+
+.dropzone .dz-preview:hover {
+    z-index: 1000
+}
+
+.dropzone .dz-preview:hover .dz-details {
+    opacity: 1
+}
+
+.dropzone .dz-preview.dz-file-preview .dz-image {
+    border-radius: 20px;
+    background: #999;
+    background: linear-gradient(to bottom, #eee, #ddd)
+}
+
+.dropzone .dz-preview.dz-file-preview .dz-details {
+    opacity: 1
+}
+
+.dropzone .dz-preview.dz-image-preview {
+    background: white
+}
+
+.dropzone .dz-preview.dz-image-preview .dz-details {
+    -webkit-transition: opacity 0.2s linear;
+    -moz-transition: opacity 0.2s linear;
+    -ms-transition: opacity 0.2s linear;
+    -o-transition: opacity 0.2s linear;
+    transition: opacity 0.2s linear
+}
+
+.dropzone .dz-preview .dz-remove {
+    font-size: 14px;
+    text-align: center;
+    display: block;
+    cursor: pointer;
+    border: none
+}
+
+.dropzone .dz-preview .dz-remove:hover {
+    text-decoration: underline
+}
+
+.dropzone .dz-preview:hover .dz-details {
+    opacity: 1
+}
+
+.dropzone .dz-preview .dz-details {
+    z-index: 20;
+    position: absolute;
+    top: 0;
+    left: 0;
+    opacity: 0;
+    font-size: 13px;
+    min-width: 100%;
+    max-width: 100%;
+    padding: 2em 1em;
+    text-align: center;
+    color: rgba(0, 0, 0, 0.9);
+    line-height: 150%
+}
+
+.dropzone .dz-preview .dz-details .dz-size {
+    margin-bottom: 1em;
+    font-size: 16px
+}
+
+.dropzone .dz-preview .dz-details .dz-filename {
+    white-space: nowrap
+}
+
+.dropzone .dz-preview .dz-details .dz-filename:hover span {
+    border: 1px solid rgba(200, 200, 200, 0.8);
+    background-color: rgba(255, 255, 255, 0.8)
+}
+
+.dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
+    overflow: hidden;
+    text-overflow: ellipsis
+}
+
+.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
+    border: 1px solid transparent
+}
+
+.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
+    background-color: rgba(255, 255, 255, 0.4);
+    padding: 0 0.4em;
+    border-radius: 3px
+}
+
+.dropzone .dz-preview:hover .dz-image img {
+    -webkit-transform: scale(1.05, 1.05);
+    -moz-transform: scale(1.05, 1.05);
+    -ms-transform: scale(1.05, 1.05);
+    -o-transform: scale(1.05, 1.05);
+    transform: scale(1.05, 1.05);
+    -webkit-filter: blur(8px);
+    filter: blur(8px)
+}
+
+.dropzone .dz-preview .dz-image {
+    border-radius: 20px;
+    overflow: hidden;
+    width: 120px;
+    height: 120px;
+    position: relative;
+    display: block;
+    z-index: 10
+}
+
+.dropzone .dz-preview .dz-image img {
+    display: block
+}
+
+.dropzone .dz-preview.dz-success .dz-success-mark {
+    -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+    -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+    -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+    -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+    animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1)
+}
+
+.dropzone .dz-preview.dz-error .dz-error-mark {
+    opacity: 1;
+    -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+    -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+    -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+    -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+    animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1)
+}
+
+.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
+    pointer-events: none;
+    opacity: 0;
+    z-index: 500;
+    position: absolute;
+    display: block;
+    top: 50%;
+    left: 50%;
+    margin-left: -27px;
+    margin-top: -27px
+}
+
+.dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
+    display: block;
+    width: 54px;
+    height: 54px
+}
+
+.dropzone .dz-preview.dz-processing .dz-progress {
+    opacity: 1;
+    -webkit-transition: all 0.2s linear;
+    -moz-transition: all 0.2s linear;
+    -ms-transition: all 0.2s linear;
+    -o-transition: all 0.2s linear;
+    transition: all 0.2s linear
+}
+
+.dropzone .dz-preview.dz-complete .dz-progress {
+    opacity: 0;
+    -webkit-transition: opacity 0.4s ease-in;
+    -moz-transition: opacity 0.4s ease-in;
+    -ms-transition: opacity 0.4s ease-in;
+    -o-transition: opacity 0.4s ease-in;
+    transition: opacity 0.4s ease-in
+}
+
+.dropzone .dz-preview:not(.dz-processing) .dz-progress {
+    -webkit-animation: pulse 6s ease infinite;
+    -moz-animation: pulse 6s ease infinite;
+    -ms-animation: pulse 6s ease infinite;
+    -o-animation: pulse 6s ease infinite;
+    animation: pulse 6s ease infinite
+}
+
+.dropzone .dz-preview .dz-progress {
+    opacity: 1;
+    z-index: 1000;
+    pointer-events: none;
+    position: absolute;
+    height: 16px;
+    left: 50%;
+    top: 50%;
+    margin-top: -8px;
+    width: 80px;
+    margin-left: -40px;
+    background: rgba(255, 255, 255, 0.9);
+    -webkit-transform: scale(1);
+    border-radius: 8px;
+    overflow: hidden
+}
+
+.dropzone .dz-preview .dz-progress .dz-upload {
+    background: #333;
+    background: linear-gradient(to bottom, #666, #444);
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    width: 0;
+    -webkit-transition: width 300ms ease-in-out;
+    -moz-transition: width 300ms ease-in-out;
+    -ms-transition: width 300ms ease-in-out;
+    -o-transition: width 300ms ease-in-out;
+    transition: width 300ms ease-in-out
+}
+
+.dropzone .dz-preview.dz-error .dz-error-message {
+    display: block
+}
+
+.dropzone .dz-preview.dz-error:hover .dz-error-message {
+    transform: scale(1.5);
+    pointer-events: auto
+}
+
+.dropzone .dz-preview .dz-error-message {
+    pointer-events: none;
+    z-index: 1000;
+    position: absolute;
+    display: block;
+    display: none;
+    opacity: 1;
+    -webkit-transition: all 0.3s ease;
+    -moz-transition: all 0.3s ease;
+    -ms-transition: all 0.3s ease;
+    -o-transition: all 0.3s ease;
+    transition: all 0.3s ease;
+    border-radius: 8px;
+    font-size: 13px;
+    top: 130px;
+    left: -10px;
+    width: 140px;
+    background: #be2626;
+    background: linear-gradient(to bottom, #be2626, #a92222);
+    padding: 0.5em 1.2em;
+    color: white
+}
+
+.dropzone .dz-preview .dz-error-message:after {
+    content: '';
+    position: absolute;
+    top: -6px;
+    left: 64px;
+    width: 0;
+    height: 0;
+    border-left: 6px solid transparent;
+    border-right: 6px solid transparent;
+    border-bottom: 6px solid #be2626
+}

+ 387 - 0
public/vendor/laravel-filemanager/css/lfm.css

@@ -0,0 +1,387 @@
+/* General */
+
+a {
+  color: #333844;
+  text-decoration: none !important;
+  cursor: pointer;
+}
+
+#nav a, #fab a {
+  color: white;
+}
+
+#nav, #nav .dropdown-menu, .bg-main {
+  background-color: #333844;
+}
+
+#nav .dropdown-menu > a:hover {
+  color: #333844;
+}
+
+#actions {
+  display: flex;
+}
+
+#actions > a {
+  display: inline-block;
+  line-height: 4rem;
+  text-align: center;
+  width: 100%;
+  font-size: 1.25rem;
+}
+
+#actions > a > i {
+  margin-right: .25rem;
+}
+
+#actions > a + a {
+  border-left: 1px solid #dee2e6;
+}
+
+#multi_selection_toggle > i {
+  font-size: 20px;
+}
+
+.breadcrumb-item:not(.active) {
+  transition: .2s color;
+}
+
+.breadcrumb-item:not(.active):hover {
+  cursor: pointer;
+  color: #75C7C3;
+}
+
+#main {
+  width: 100%;
+}
+
+@media screen and (min-width: 992px) {
+  #main {
+    width: calc(100% - 300px);
+    /*margin-left: 1rem;*/
+    padding: 1rem;
+  }
+
+  .invisible-lg {
+    visibility: hidden;
+  }
+}
+
+#tree {
+  background-color: white;
+  width: 300px;
+}
+
+@media screen and (max-width: 991px) {
+  #tree {
+    position: absolute;
+    z-index: 999;
+    left: 0;
+    transform: translateX(-100%);
+    transition: 1s transform;
+  }
+
+  #tree.in {
+    transform: translateX(0);
+  }
+}
+
+#empty {
+  height: 60vh;
+  color: #333844;
+}
+
+#empty:not(.d-none) {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+}
+
+#empty > i {
+  font-size: 10rem;
+}
+
+.carousel-image {
+  height: 50vh;
+  background-position: center;
+  background-size: contain;
+  background-repeat: no-repeat;
+  margin: 0 auto;
+}
+
+.carousel-indicators {
+  bottom: 0;
+}
+
+.carousel-label, .carousel-label:hover {
+  position: absolute;
+  bottom: 0;
+  background: linear-gradient(transparent 10px, rgba(0, 0, 0, .4), rgba(0, 0, 0, .5));
+  padding: 40px 20px 30px;
+  width: 100%;
+  color: white;
+  word-break: break-word;
+  text-align: center;
+}
+
+.carousel-control-background {
+  border-radius: 50%;
+  width: 25px;
+  height: 25px;
+  box-shadow: 0 0 10px #666;
+  background-color: #666;
+}
+
+#uploadForm > .dz-default.dz-message {
+  border: 2px dashed #ccc;
+  border-radius: 5px;
+  color: #aaa;
+  margin: 0;
+  padding: 3rem 0;
+}
+
+/* Loader */
+
+#lfm-loader {
+  display: none;
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: gray;
+  opacity: 0.7;
+  z-index: 9999;
+  text-align: center;
+}
+#lfm-loader:before {
+  content: "";
+  display: inline-block;
+  vertical-align: middle;
+  height: 100%;
+}
+#lfm-loader img {
+  width: 100px;
+  margin: 0 auto;
+  display: inline-block;
+  vertical-align: middle;
+}
+
+/* Sidebar */
+
+.nav-pills > .nav-item > .nav-link {
+  height: 5rem;
+  display: flex;
+  align-items: center;
+}
+
+.nav-pills > .sub-item > .nav-link {
+  height: 3rem;
+  padding-left: 3rem;
+}
+
+.nav-pills > li.active > a, .nav-pills > li:hover > a {
+  background-color: #ddd;
+  border-radius: 0;
+  color: #333844;
+}
+
+/* Items */
+
+#pagination > ul.pagination {
+  justify-content: center;
+}
+
+#pagination.preserve_actions_space {
+  padding-top: 1em;
+  padding-bottom: 4rem; /* preserve space for main actions */
+}
+
+.square {
+  cursor: pointer;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 5px;
+}
+
+.grid {
+  display: flex;
+  flex-wrap: wrap;
+  padding: .5rem;
+  justify-content: center;
+}
+
+.grid a {
+  margin: .5rem;
+  display: flex;
+  flex-direction: column;
+}
+
+.list a {
+  border-top: 1px solid rgb(221, 221, 221);
+  padding: 5px;
+  margin-top: 0;
+  display: flex;
+  flex-direction: row;
+}
+
+.list a:last-child {
+  border-bottom: 1px solid rgb(221, 221, 221);
+}
+
+.grid .square {
+  border: 1px solid rgb(221, 221, 221);
+  width: 135px;
+  height: 135px;
+}
+
+.list .square {
+  margin-right: 1rem;
+  width: 70px;
+  height: 70px;
+}
+
+.square > div {
+  width: 100%;
+  height: 100%;
+  background-size: cover;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+
+.square > i {
+  color: #333844;
+}
+.grid .square > i {
+  padding: 20px;
+  font-size: 80px;
+}
+.list .square > i {
+  padding: 10px;
+  font-size: 50px;
+}
+
+.grid .square.selected {
+  border: 5px solid #75C7C3;
+}
+.list .square.selected {
+  border: 4px solid #75C7C3;
+}
+.square.selected {
+  padding: 1px;
+}
+
+.grid .item_name {
+  border: 1px solid rgb(221, 221, 221);
+  border-top: none;
+  margin-top: -1px;
+  padding: 10px;
+  text-align: center;
+  max-width: calc(135px);
+}
+
+.list .item_name {
+  font-size: 1.25rem;
+  padding: 5px 0 5px;
+}
+
+time {
+  font-size: .9rem;
+}
+
+.grid time {
+  display: none;
+}
+
+.info > * {
+  max-width: calc(100vw - 70px - 60px);
+}
+
+/* Mime icon generator overwrite */
+
+.grid .mime-icon:before {
+  top: calc(45% - 1rem);
+  font-size: 2rem;
+}
+
+.list .mime-icon .ico:before {
+  top: calc(45% - .5rem);
+  font-size: 1rem;
+}
+
+.mime-icon .ico {
+  height: 100%;
+  display: inline-flex;
+  align-items: center;
+  width: 100%;
+  justify-content: center;
+}
+
+/* Floating action buttons */
+
+.fab-wrapper {
+  margin: 1.5rem;
+  right: 0;
+  bottom: 0;
+  position: fixed;
+}
+
+.fab-wrapper .fab-button {
+  position: relative;
+  background-color: #333844;
+  width: 3.5rem;
+  height: 3.5rem;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 1.25rem;
+  box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28);
+}
+
+.fab-wrapper .fab-toggle {
+  z-index: 1;
+}
+
+.fab-wrapper .fab-toggle i {
+  -webkit-transform: scale(1) rotate(0deg);
+  transform: scale(1) rotate(0deg);
+  -webkit-transition: -webkit-transform 350ms;
+  transition: transform 350ms;
+}
+
+.fab-wrapper.fab-expand .fab-toggle i {
+  -webkit-transform: scale(1) rotate(-225deg);
+  transform: scale(1) rotate(-225deg);
+  -webkit-transition: -webkit-transform 350ms;
+  transition: transform 350ms;
+}
+
+.fab-wrapper .fab-action {
+  z-index: -1;
+  margin-bottom: -3.5rem;
+  opacity: 0;
+  transition: margin-bottom 350ms, opacity 350ms;
+}
+
+.fab-wrapper.fab-expand .fab-action {
+  margin-bottom: 1rem;
+  opacity: 1;
+  transition: margin-bottom 350ms, opacity 350ms;
+}
+
+.fab-wrapper .fab-action:before {
+  position: absolute;
+  right: 4rem;
+  padding: .15rem .75rem;
+  border-radius: .25rem;
+  background-color: rgba(0, 0, 0, .4);
+  color: rgba(255, 255, 255, .8);
+  text-align: right;
+  font-size: .9rem;
+  white-space: nowrap;
+  content: attr(data-label);
+}

文件差異過大導致無法顯示
+ 8 - 0
public/vendor/laravel-filemanager/css/mime-icons.min.css


+ 0 - 0
public/vendor/laravel-filemanager/files/.gitkeep


二進制
public/vendor/laravel-filemanager/files/adobe.pdf


二進制
public/vendor/laravel-filemanager/files/folder-1/sleeping-dog.jpg


二進制
public/vendor/laravel-filemanager/files/word.docx


+ 0 - 0
public/vendor/laravel-filemanager/images/.gitkeep


二進制
public/vendor/laravel-filemanager/images/test-folder/sleeping-dog.jpg


二進制
public/vendor/laravel-filemanager/images/test-folder/thumbs/sleeping-dog.jpg


二進制
public/vendor/laravel-filemanager/img/152px color.png


二進制
public/vendor/laravel-filemanager/img/72px color.png


二進制
public/vendor/laravel-filemanager/img/92px color.png


二進制
public/vendor/laravel-filemanager/img/Logomark color.png


二進制
public/vendor/laravel-filemanager/img/folder.png


+ 33 - 0
public/vendor/laravel-filemanager/img/loader.svg

@@ -0,0 +1,33 @@
+<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
+<svg width="120" height="30" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="#fff">
+    <circle cx="15" cy="15" r="15">
+        <animate attributeName="r" from="15" to="15"
+                 begin="0s" dur="0.8s"
+                 values="15;9;15" calcMode="linear"
+                 repeatCount="indefinite" />
+        <animate attributeName="fill-opacity" from="1" to="1"
+                 begin="0s" dur="0.8s"
+                 values="1;.5;1" calcMode="linear"
+                 repeatCount="indefinite" />
+    </circle>
+    <circle cx="60" cy="15" r="9" fill-opacity="0.3">
+        <animate attributeName="r" from="9" to="9"
+                 begin="0s" dur="0.8s"
+                 values="9;15;9" calcMode="linear"
+                 repeatCount="indefinite" />
+        <animate attributeName="fill-opacity" from="0.5" to="0.5"
+                 begin="0s" dur="0.8s"
+                 values=".5;1;.5" calcMode="linear"
+                 repeatCount="indefinite" />
+    </circle>
+    <circle cx="105" cy="15" r="15">
+        <animate attributeName="r" from="15" to="15"
+                 begin="0s" dur="0.8s"
+                 values="15;9;15" calcMode="linear"
+                 repeatCount="indefinite" />
+        <animate attributeName="fill-opacity" from="1" to="1"
+                 begin="0s" dur="0.8s"
+                 values="1;.5;1" calcMode="linear"
+                 repeatCount="indefinite" />
+    </circle>
+</svg>

文件差異過大導致無法顯示
+ 9 - 0
public/vendor/laravel-filemanager/js/cropper.min.js


文件差異過大導致無法顯示
+ 0 - 0
public/vendor/laravel-filemanager/js/dropzone.min.js


+ 812 - 0
public/vendor/laravel-filemanager/js/script.js

@@ -0,0 +1,812 @@
+var lfm_route = location.origin + location.pathname;
+var show_list;
+var sort_type = 'alphabetic';
+var multi_selection_enabled = false;
+var selected = [];
+var items = [];
+
+$.fn.fab = function (options) {
+  var menu = this;
+  menu.addClass('fab-wrapper');
+
+  var toggler = $('<a>')
+    .addClass('fab-button fab-toggle')
+    .append($('<i>').addClass('fas fa-plus'))
+    .click(function () {
+      menu.toggleClass('fab-expand');
+    });
+
+  menu.append(toggler);
+
+  options.buttons.forEach(function (button) {
+    toggler.before(
+      $('<a>').addClass('fab-button fab-action')
+        .attr('data-label', button.label)
+        .attr('id', button.attrs.id)
+        .append($('<i>').addClass(button.icon))
+        .click(function () {
+          menu.removeClass('fab-expand');
+        })
+    );
+  });
+};
+
+$(document).ready(function () {
+  $('#fab').fab({
+    buttons: [
+      {
+        icon: 'fas fa-upload',
+        label: lang['nav-upload'],
+        attrs: {id: 'upload'}
+      },
+      {
+        icon: 'fas fa-folder',
+        label: lang['nav-new'],
+        attrs: {id: 'add-folder'}
+      }
+    ]
+  });
+
+  actions.reverse().forEach(function (action) {
+    $('#nav-buttons > ul').prepend(
+      $('<li>').addClass('nav-item').append(
+        $('<a>').addClass('nav-link d-none')
+          .attr('data-action', action.name)
+          .attr('data-multiple', action.multiple)
+          .append($('<i>').addClass('fas fa-fw fa-' + action.icon))
+          .append($('<span>').text(action.label))
+      )
+    );
+  });
+
+  sortings.forEach(function (sort) {
+    $('#nav-buttons .dropdown-menu').append(
+      $('<a>').addClass('dropdown-item').attr('data-sortby', sort.by)
+        .append($('<i>').addClass('fas fa-fw fa-' + sort.icon))
+        .append($('<span>').text(sort.label))
+        .click(function() {
+          sort_type = sort.by;
+          loadItems();
+        })
+    );
+  });
+
+  loadFolders();
+  performLfmRequest('errors')
+    .done(function (response) {
+      JSON.parse(response).forEach(function (message) {
+        $('#alerts').append(
+          $('<div>').addClass('alert alert-warning')
+            .append($('<i>').addClass('fas fa-exclamation-circle'))
+            .append(' ' + message)
+        );
+      });
+    });
+
+  $(window).on('dragenter', function(){
+    $('#uploadModal').modal('show');
+  });
+
+  if (usingWysiwygEditor()) {
+    $('#multi_selection_toggle').hide();
+  }
+});
+
+// ======================
+// ==  Navbar actions  ==
+// ======================
+
+$('#multi_selection_toggle').click(function () {
+  multi_selection_enabled = !multi_selection_enabled;
+
+  $('#multi_selection_toggle i')
+    .toggleClass('fa-times', multi_selection_enabled)
+    .toggleClass('fa-check-double', !multi_selection_enabled);
+
+  if (!multi_selection_enabled) {
+    clearSelected();
+  }
+});
+
+$('#to-previous').click(function () {
+  var previous_dir = getPreviousDir();
+  if (previous_dir == '') return;
+  goTo(previous_dir);
+});
+
+function toggleMobileTree(should_display) {
+  if (should_display === undefined) {
+    should_display = !$('#tree').hasClass('in');
+  }
+  $('#tree').toggleClass('in', should_display);
+}
+
+$('#show_tree').click(function (e) {
+  toggleMobileTree();
+});
+
+$('#main').click(function (e) {
+  if ($('#tree').hasClass('in')) {
+    toggleMobileTree(false);
+  }
+});
+
+$(document).on('click', '#add-folder', function () {
+  dialog(lang['message-name'], '', createFolder);
+});
+
+$(document).on('click', '#upload', function () {
+  $('#uploadModal').modal('show');
+});
+
+$(document).on('click', '[data-display]', function() {
+  show_list = $(this).data('display');
+  loadItems();
+});
+
+$(document).on('click', '[data-action]', function() {
+  window[$(this).data('action')]($(this).data('multiple') ? getSelectedItems() : getOneSelectedElement());
+});
+
+// ==========================
+// ==  Multiple Selection  ==
+// ==========================
+
+function toggleSelected (e) {
+  if (!multi_selection_enabled) {
+    selected = [];
+  }
+
+  var sequence = $(e.target).closest('a').data('id');
+  var element_index = selected.indexOf(sequence);
+  if (element_index === -1) {
+    selected.push(sequence);
+  } else {
+    selected.splice(element_index, 1);
+  }
+
+  updateSelectedStyle();
+}
+
+function clearSelected () {
+  selected = [];
+
+  multi_selection_enabled = false;
+
+  updateSelectedStyle();
+}
+
+function updateSelectedStyle() {
+  items.forEach(function (item, index) {
+    $('[data-id=' + index + ']')
+      .find('.square')
+      .toggleClass('selected', selected.indexOf(index) > -1);
+  });
+  toggleActions();
+}
+
+function getOneSelectedElement(orderOfItem) {
+  var index = orderOfItem !== undefined ? orderOfItem : selected[0];
+  return items[index];
+}
+
+function getSelectedItems() {
+  return selected.reduce(function (arr_objects, id) {
+    arr_objects.push(getOneSelectedElement(id));
+    return arr_objects
+  }, []);
+}
+
+function toggleActions() {
+  var one_selected = selected.length === 1;
+  var many_selected = selected.length >= 1;
+  var only_image = getSelectedItems()
+    .filter(function (item) { return !item.is_image; })
+    .length === 0;
+  var only_file = getSelectedItems()
+    .filter(function (item) { return !item.is_file; })
+    .length === 0;
+
+  $('[data-action=use]').toggleClass('d-none', !(many_selected && only_file));
+  $('[data-action=rename]').toggleClass('d-none', !one_selected);
+  $('[data-action=preview]').toggleClass('d-none', !(many_selected && only_file));
+  $('[data-action=move]').toggleClass('d-none', !many_selected);
+  $('[data-action=download]').toggleClass('d-none', !(many_selected && only_file));
+  $('[data-action=resize]').toggleClass('d-none', !(one_selected && only_image));
+  $('[data-action=crop]').toggleClass('d-none', !(one_selected && only_image));
+  $('[data-action=trash]').toggleClass('d-none', !many_selected);
+  $('[data-action=open]').toggleClass('d-none', !one_selected || only_file);
+  $('#multi_selection_toggle').toggleClass('d-none', usingWysiwygEditor() || !many_selected);
+  $('#actions').toggleClass('d-none', selected.length === 0);
+  $('#fab').toggleClass('d-none', selected.length !== 0);
+}
+
+// ======================
+// ==  Folder actions  ==
+// ======================
+
+$(document).on('click', '#tree a', function (e) {
+  goTo($(e.target).closest('a').data('path'));
+  toggleMobileTree(false);
+});
+
+function goTo(new_dir) {
+  $('#working_dir').val(new_dir);
+  loadItems();
+}
+
+function getPreviousDir() {
+  var working_dir = $('#working_dir').val();
+  return working_dir.substring(0, working_dir.lastIndexOf('/'));
+}
+
+function setOpenFolders() {
+  $('#tree [data-path]').each(function (index, folder) {
+    // close folders that are not parent
+    var should_open = ($('#working_dir').val() + '/').startsWith($(folder).data('path') + '/');
+    $(folder).children('i')
+      .toggleClass('fa-folder-open', should_open)
+      .toggleClass('fa-folder', !should_open);
+  });
+
+  $('#tree .nav-item').removeClass('active');
+  $('#tree [data-path="' + $('#working_dir').val() + '"]').parent('.nav-item').addClass('active');
+}
+
+// ====================
+// ==  Ajax actions  ==
+// ====================
+
+function performLfmRequest(url, parameter, type) {
+  var data = defaultParameters();
+
+  if (parameter != null) {
+    $.each(parameter, function (key, value) {
+      data[key] = value;
+    });
+  }
+
+  return $.ajax({
+    type: 'GET',
+    beforeSend: function(request) {
+      var token = getUrlParam('token');
+      if (token !== null) {
+        request.setRequestHeader("Authorization", 'Bearer ' + token);
+      }
+    },
+    dataType: type || 'text',
+    url: lfm_route + '/' + url,
+    data: data,
+    cache: false
+  }).fail(function (jqXHR, textStatus, errorThrown) {
+    displayErrorResponse(jqXHR);
+  });
+}
+
+function displayErrorResponse(jqXHR) {
+  notify('<div style="max-height:50vh;overflow: scroll;">' + jqXHR.responseText + '</div>');
+}
+
+var refreshFoldersAndItems = function (data) {
+  loadFolders();
+  if (data != 'OK') {
+    data = Array.isArray(data) ? data.join('<br/>') : data;
+    notify(data);
+  }
+};
+
+var hideNavAndShowEditor = function (data) {
+  $('#nav-buttons > ul').addClass('d-none');
+  $('#content').html(data);
+  $('#pagination').removeClass('preserve_actions_space')
+  clearSelected();
+}
+
+function loadFolders() {
+  performLfmRequest('folders', {}, 'html')
+    .done(function (data) {
+      $('#tree').html(data);
+      loadItems();
+    });
+}
+
+function generatePaginationHTML(el, args) {
+  var template = '<li class="page-item"><\/li>';
+  var linkTemplate = '<a class="page-link"><\/a>';
+  var currentPage = args.currentPage;
+  var totalPage = args.totalPage;
+  var rangeStart = args.rangeStart;
+  var rangeEnd = args.rangeEnd;
+  var i;
+
+  // Disable page range, display all the pages
+  if (args.pageRange === null) {
+    for (i = 1; i <= totalPage; i++) {
+      var button = $(template)
+        .attr('data-num', i)
+        .append($(linkTemplate).html(i));
+      if (i == currentPage) {
+        button.addClass('active');
+      }
+      el.append(button);
+    }
+
+    return;
+  }
+
+  if (rangeStart <= 3) {
+    for (i = 1; i < rangeStart; i++) {
+      var button = $(template)
+        .attr('data-num', i)
+        .append($(linkTemplate).html(i));
+      if (i == currentPage) {
+        button.addClass('active');
+      }
+      el.append(button);
+    }
+  } else {
+    var button = $(template)
+      .attr('data-num', 1)
+      .append($(linkTemplate).html(1));
+    el.append(button);
+
+    var button = $(template)
+      .addClass('disabled')
+      .append($(linkTemplate).html('...'));
+    el.append(button);
+  }
+
+  for (i = rangeStart; i <= rangeEnd; i++) {
+    var button = $(template)
+      .attr('data-num', i)
+      .append($(linkTemplate).html(i));
+    if (i == currentPage) {
+      button.addClass('active');
+    }
+    el.append(button);
+  }
+
+  if (rangeEnd >= totalPage - 2) {
+    for (i = rangeEnd + 1; i <= totalPage; i++) {
+      var button = $(template)
+        .attr('data-num', i)
+        .append($(linkTemplate).html(i));
+      el.append(button);
+    }
+  } else {
+    var button = $(template)
+      .addClass('disabled')
+      .append($(linkTemplate).html('...'));
+    el.append(button);
+
+    var button = $(template)
+      .attr('data-num', totalPage)
+      .append($(linkTemplate).html(totalPage));
+    el.append(button);
+  }
+}
+
+function createPagination(paginationSetting) {
+  var el = $('<ul class="pagination" role="navigation"></ul>');
+
+  var currentPage = paginationSetting.current_page;
+  var pageRange = 5;
+  var totalPage = Math.ceil(paginationSetting.total / paginationSetting.per_page);
+
+  var rangeStart = currentPage - pageRange;
+  var rangeEnd = currentPage + pageRange;
+
+  if (rangeEnd > totalPage) {
+    rangeEnd = totalPage;
+    rangeStart = totalPage - pageRange * 2;
+    rangeStart = rangeStart < 1 ? 1 : rangeStart;
+  }
+
+  if (rangeStart <= 1) {
+    rangeStart = 1;
+    rangeEnd = Math.min(pageRange * 2 + 1, totalPage);
+  }
+
+  generatePaginationHTML(el, {
+    totalPage: totalPage,
+    currentPage: currentPage,
+    pageRange: pageRange,
+    rangeStart: rangeStart,
+    rangeEnd: rangeEnd
+  });
+
+  $('#pagination').append(el);
+}
+
+function loadItems(page) {
+  loading(true);
+  performLfmRequest('jsonitems', {show_list: show_list, sort_type: sort_type, page: page || 1}, 'html')
+    .done(function (data) {
+      selected = [];
+      var response = JSON.parse(data);
+      var working_dir = response.working_dir;
+      items = response.items;
+      var hasItems = items.length !== 0;
+      var hasPaginator = !!response.paginator;
+      $('#empty').toggleClass('d-none', hasItems);
+      $('#content').html('').removeAttr('class');
+      $('#pagination').html('').removeAttr('class');
+
+      if (hasItems) {
+        $('#content').addClass(response.display);
+        $('#pagination').addClass('preserve_actions_space');
+
+        items.forEach(function (item, index) {
+          var template = $('#item-template').clone()
+            .removeAttr('id class')
+            .attr('data-id', index)
+            .click(toggleSelected)
+            .dblclick(function (e) {
+              if (item.is_file) {
+                use(getSelectedItems());
+              } else {
+                goTo(item.url);
+              }
+            });
+
+          if (item.thumb_url) {
+            var image = $('<div>').css('background-image', 'url("' + item.thumb_url + '?timestamp=' + item.time + '")');
+          } else {
+            var icon = $('<div>').addClass('ico');
+            var image = $('<div>').addClass('mime-icon ico-' + item.icon).append(icon);
+          }
+
+          template.find('.square').append(image);
+          template.find('.item_name').text(item.name);
+          template.find('time').text((new Date(item.time * 1000)).toLocaleString());
+
+          $('#content').append(template);
+        });
+      }
+
+      if (hasPaginator) {
+        createPagination(response.paginator);
+
+        $('#pagination a').on('click', function(event) {
+          event.preventDefault();
+
+          loadItems($(this).closest('li')[0].getAttribute('data-num'));
+
+          return false;
+        });
+      }
+
+      $('#nav-buttons > ul').removeClass('d-none');
+
+      $('#working_dir').val(working_dir);
+      console.log('Current working_dir : ' + working_dir);
+      var breadcrumbs = [];
+      var validSegments = working_dir.split('/').filter(function (e) { return e; });
+      validSegments.forEach(function (segment, index) {
+        if (index === 0) {
+          // set root folder name as the first breadcrumb
+          breadcrumbs.push($("[data-path='/" + segment + "']").text());
+        } else {
+          breadcrumbs.push(segment);
+        }
+      });
+
+      $('#current_folder').text(breadcrumbs[breadcrumbs.length - 1]);
+      $('#breadcrumbs > ol').html('');
+      breadcrumbs.forEach(function (breadcrumb, index) {
+        var li = $('<li>').addClass('breadcrumb-item').text(breadcrumb);
+
+        if (index === breadcrumbs.length - 1) {
+          li.addClass('active').attr('aria-current', 'page');
+        } else {
+          li.click(function () {
+            // go to corresponding path
+            goTo('/' + validSegments.slice(0, 1 + index).join('/'));
+          });
+        }
+
+        $('#breadcrumbs > ol').append(li);
+      });
+
+      var atRootFolder = getPreviousDir() == '';
+      $('#to-previous').toggleClass('d-none invisible-lg', atRootFolder);
+      $('#show_tree').toggleClass('d-none', !atRootFolder).toggleClass('d-block', atRootFolder);
+      setOpenFolders();
+      loading(false);
+      toggleActions();
+    });
+}
+
+function loading(show_loading) {
+  $('#loading').toggleClass('d-none', !show_loading);
+}
+
+function createFolder(folder_name) {
+  performLfmRequest('newfolder', {name: folder_name})
+    .done(refreshFoldersAndItems);
+}
+
+// ==================================
+// ==         File Actions         ==
+// ==================================
+
+function rename(item) {
+  dialog(lang['message-rename'], item.name, function (new_name) {
+    performLfmRequest('rename', {
+      file: item.name,
+      new_name: new_name
+    }).done(refreshFoldersAndItems);
+  });
+}
+
+function trash(items) {
+  notify(lang['message-delete'], function () {
+    performLfmRequest('delete', {
+      items: items.map(function (item) { return item.name; })
+    }).done(refreshFoldersAndItems)
+  });
+}
+
+function crop(item) {
+  performLfmRequest('crop', {img: item.name})
+    .done(hideNavAndShowEditor);
+}
+
+function resize(item) {
+  performLfmRequest('resize', {img: item.name})
+    .done(hideNavAndShowEditor);
+}
+
+function download(items) {
+  items.forEach(function (item, index) {
+    var data = defaultParameters();
+
+    data['file'] = item.name;
+
+    var token = getUrlParam('token');
+    if (token) {
+      data['token'] = token;
+    }
+
+    setTimeout(function () {
+      location.href = lfm_route + '/download?' + $.param(data);
+    }, index * 100);
+  });
+}
+
+function open(item) {
+  goTo(item.url);
+}
+
+function preview(items) {
+  var carousel = $('#carouselTemplate').clone().attr('id', 'previewCarousel').removeClass('d-none');
+  var imageTemplate = carousel.find('.carousel-item').clone().removeClass('active');
+  var indicatorTemplate = carousel.find('.carousel-indicators > li').clone().removeClass('active');
+  carousel.children('.carousel-inner').html('');
+  carousel.children('.carousel-indicators').html('');
+  carousel.children('.carousel-indicators,.carousel-control-prev,.carousel-control-next').toggle(items.length > 1);
+
+  items.forEach(function (item, index) {
+    var carouselItem = imageTemplate.clone()
+      .addClass(index === 0 ? 'active' : '');
+
+    if (item.thumb_url) {
+      carouselItem.find('.carousel-image').css('background-image', 'url(\'' + item.url + '?timestamp=' + item.time + '\')');
+    } else {
+      carouselItem.find('.carousel-image').css('width', '50vh').append($('<div>').addClass('mime-icon ico-' + item.icon));
+    }
+
+    carouselItem.find('.carousel-label').attr('target', '_blank').attr('href', item.url)
+      .append(item.name)
+      .append($('<i class="fas fa-external-link-alt ml-2"></i>'));
+
+    carousel.children('.carousel-inner').append(carouselItem);
+
+    var carouselIndicator = indicatorTemplate.clone()
+      .addClass(index === 0 ? 'active' : '')
+      .attr('data-slide-to', index);
+    carousel.children('.carousel-indicators').append(carouselIndicator);
+  });
+
+
+  // carousel swipe control
+  var touchStartX = null;
+
+  carousel.on('touchstart', function (event) {
+    var e = event.originalEvent;
+    if (e.touches.length == 1) {
+      var touch = e.touches[0];
+      touchStartX = touch.pageX;
+    }
+  }).on('touchmove', function (event) {
+    var e = event.originalEvent;
+    if (touchStartX != null) {
+      var touchCurrentX = e.changedTouches[0].pageX;
+      if ((touchCurrentX - touchStartX) > 60) {
+        touchStartX = null;
+        carousel.carousel('prev');
+      } else if ((touchStartX - touchCurrentX) > 60) {
+        touchStartX = null;
+        carousel.carousel('next');
+      }
+    }
+  }).on('touchend', function () {
+    touchStartX = null;
+  });
+  // end carousel swipe control
+
+  notify(carousel);
+}
+
+function move(items) {
+  performLfmRequest('move', { items: items.map(function (item) { return item.name; }) })
+    .done(refreshFoldersAndItems);
+}
+
+function getUrlParam(paramName) {
+  var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i');
+  var match = window.location.search.match(reParam);
+  return ( match && match.length > 1 ) ? match[1] : null;
+}
+
+function use(items) {
+  function useTinymce3(url) {
+    if (!usingTinymce3()) { return; }
+
+    var win = tinyMCEPopup.getWindowArg("window");
+    win.document.getElementById(tinyMCEPopup.getWindowArg("input")).value = url;
+    if (typeof(win.ImageDialog) != "undefined") {
+      // Update image dimensions
+      if (win.ImageDialog.getImageData) {
+        win.ImageDialog.getImageData();
+      }
+
+      // Preview if necessary
+      if (win.ImageDialog.showPreviewImage) {
+        win.ImageDialog.showPreviewImage(url);
+      }
+    }
+    tinyMCEPopup.close();
+  }
+
+  function useTinymce4AndColorbox(url) {
+    if (!usingTinymce4AndColorbox()) { return; }
+
+    parent.document.getElementById(getUrlParam('field_name')).value = url;
+
+    if(typeof parent.tinyMCE !== "undefined") {
+      parent.tinyMCE.activeEditor.windowManager.close();
+    }
+    if(typeof parent.$.fn.colorbox !== "undefined") {
+      parent.$.fn.colorbox.close();
+    }
+  }
+
+  function useTinymce5(url){
+    if (!usingTinymce5()) { return; }
+
+    parent.postMessage({
+      mceAction: 'insert',
+      content: url
+    });
+
+    parent.postMessage({ mceAction: 'close' });
+  }
+
+  function useCkeditor3(url) {
+    if (!usingCkeditor3()) { return; }
+
+    if (window.opener) {
+      // Popup
+      window.opener.CKEDITOR.tools.callFunction(getUrlParam('CKEditorFuncNum'), url);
+    } else {
+      // Modal (in iframe)
+      parent.CKEDITOR.tools.callFunction(getUrlParam('CKEditorFuncNum'), url);
+      parent.CKEDITOR.tools.callFunction(getUrlParam('CKEditorCleanUpFuncNum'));
+    }
+  }
+
+  function useFckeditor2(url) {
+    if (!usingFckeditor2()) { return; }
+
+    var p = url;
+    var w = data['Properties']['Width'];
+    var h = data['Properties']['Height'];
+    window.opener.SetUrl(p,w,h);
+  }
+
+  var url = items[0].url;
+  var callback = getUrlParam('callback');
+  var useFileSucceeded = true;
+
+  if (usingWysiwygEditor()) {
+    useTinymce3(url);
+
+    useTinymce4AndColorbox(url);
+
+    useTinymce5(url);
+
+    useCkeditor3(url);
+
+    useFckeditor2(url);
+  } else if (callback && window[callback]) {
+    window[callback](getSelectedItems());
+  } else if (callback && parent[callback]) {
+    parent[callback](getSelecteditems());
+  } else if (window.opener) { // standalone button or other situations
+    window.opener.SetUrl(getSelectedItems());
+  } else {
+    useFileSucceeded = false;
+  }
+
+  if (useFileSucceeded) {
+    if (window.opener) {
+      window.close();
+    }
+  } else {
+    console.log('window.opener not found');
+    // No editor found, open/download file using browser's default method
+    window.open(url);
+  }
+}
+//end useFile
+
+// ==================================
+// ==     WYSIWYG Editors Check    ==
+// ==================================
+
+function usingTinymce3() {
+  return !!window.tinyMCEPopup;
+}
+
+function usingTinymce4AndColorbox() {
+  return !!getUrlParam('field_name');
+}
+
+function usingTinymce5(){
+    return !!getUrlParam('editor');
+}
+
+function usingCkeditor3() {
+  return !!getUrlParam('CKEditor') || !!getUrlParam('CKEditorCleanUpFuncNum');
+}
+
+function usingFckeditor2() {
+  return window.opener && typeof data != 'undefined' && data['Properties']['Width'] != '';
+}
+
+function usingWysiwygEditor() {
+  return usingTinymce3() || usingTinymce4AndColorbox() || usingTinymce5() || usingCkeditor3() || usingFckeditor2();
+}
+
+// ==================================
+// ==            Others            ==
+// ==================================
+
+function defaultParameters() {
+  return {
+    working_dir: $('#working_dir').val(),
+    type: $('#type').val()
+  };
+}
+
+function notImp() {
+  notify('Not yet implemented!');
+}
+
+function notify(body, callback) {
+  $('#notify').find('.btn-primary').toggle(callback !== undefined);
+  $('#notify').find('.btn-primary').unbind().click(callback);
+  $('#notify').modal('show').find('.modal-body').html(body);
+}
+
+function dialog(title, value, callback) {
+  $('#dialog').find('input').val(value);
+  $('#dialog').on('shown.bs.modal', function () {
+    $('#dialog').find('input').focus();
+  });
+  $('#dialog').find('.btn-primary').unbind().click(function (e) {
+    callback($('#dialog').find('input').val());
+  });
+  $('#dialog').modal('show').find('.modal-title').text(title);
+}

+ 36 - 0
public/vendor/laravel-filemanager/js/stand-alone-button.js

@@ -0,0 +1,36 @@
+(function( $ ){
+
+  $.fn.filemanager = function(type, options) {
+    type = type || 'file';
+
+    this.on('click', function(e) {
+      var route_prefix = (options && options.prefix) ? options.prefix : '/filemanager';
+      var target_input = $('#' + $(this).data('input'));
+      var target_preview = $('#' + $(this).data('preview'));
+      window.open(route_prefix + '?type=' + type, 'FileManager', 'width=900,height=600');
+      window.SetUrl = function (items) {
+        var file_path = items.map(function (item) {
+          return item.url;
+        }).join(',');
+
+        // set the value of the desired input to image url
+        target_input.val('').val(file_path).trigger('change');
+
+        // clear previous preview
+        target_preview.html('');
+
+        // set or change the preview image src
+        items.forEach(function (item) {
+          target_preview.append(
+            $('<img>').css('height', '5rem').attr('src', item.thumb_url)
+          );
+        });
+
+        // trigger change event
+        target_preview.trigger('change');
+      };
+      return false;
+    });
+  }
+
+})(jQuery);

+ 33 - 0
resources/js/panel/panel.js

@@ -41,8 +41,41 @@ require('../app');
   });
 $('.select2-simple').select2();
 //***************************************************************
+// setting tinymce(editor)
+var editor_config = {
+    path_absolute : "/",
+    selector: "#editor",
+    plugins: [
+        "advlist autolink lists link image charmap print preview hr anchor pagebreak",
+        "searchreplace wordcount visualblocks visualchars code fullscreen",
+        "insertdatetime media nonbreaking save table contextmenu directionality",
+        "emoticons template paste textcolor colorpicker textpattern"
+    ],
+    toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media",
+    relative_urls: false,
+    file_browser_callback : function(field_name, url, type, win) {
+        var x = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
+        var y = window.innerHeight|| document.documentElement.clientHeight|| document.getElementsByTagName('body')[0].clientHeight;
 
+        var cmsURL = editor_config.path_absolute + 'laravel-filemanager?field_name=' + field_name;
+        if (type == 'image') {
+            cmsURL = cmsURL + "&type=Images";
+        } else {
+            cmsURL = cmsURL + "&type=Files";
+        }
 
+        tinyMCE.activeEditor.windowManager.open({
+            file : cmsURL,
+            title : 'Filemanager',
+            width : x * 0.8,
+            height : y * 0.8,
+            resizable : "yes",
+            close_previous : "no"
+        });
+    }
+};
+
+tinymce.init(editor_config);
 //******************************************************
 
 

+ 3 - 1
resources/views/panel/layouts/app.blade.php

@@ -35,10 +35,12 @@
     </div>
 
     <!-- Scripts -->
-
+    {{--script for tinymce editor--}}
+    <script src='https://cloud.tinymce.com/stable/tinymce.min.js'></script>
     <script src="{{ mix('js/panel.js') }}"></script>
     <script src="{{ mix('js/product.js') }}"></script>
 
+
     @include('sweet::alert')
     @yield('script')
 

+ 3 - 0
routes/panel/web.php

@@ -1,6 +1,9 @@
 <?php
 
 use Illuminate\Support\Facades\Route;
+Route::group(['prefix' => 'laravel-filemanager', 'middleware' => ['web', 'auth']], function () {
+    \UniSharp\LaravelFilemanager\Lfm::routes();
+});
 
 Route::get('/', 'PanelController@index')->name('panel');
 

部分文件因文件數量過多而無法顯示