diff --git a/logs/v2.3.7.txt b/logs/v2.3.7.txt
deleted file mode 100644
index ac35c40..0000000
--- a/logs/v2.3.7.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-## New
-
-- you can now use “shift + click” to limit bulk selection to specific files.
-- added new shortcuts
-- you can now copy files/folders instead of moving as well.
-- add new option for path breadcrumb for mobile to make it easier to navigate
-- add audio for success & alert ops
-- don't reset the selection if (deleting/moving/copying) an item has returned an error.
-
-## Fix
-
-- some fixes & cleanups here and there
-- fixed issue with local-storage overriding the original keys
-- fixed update folder info after moving
-- fixed not selecting an item after getting the files from server “rare”
-- fixed refreshing the manager when using “key modifier + r”
-- fixed the hardcoded translation & now all handled through laravel.
-- fixed pre-mature selection of first item after delete/move form submit
-- fixed showing an empty notification
-- fixed axios showing vague error message
-
-## Update
-
-- cleanup & optimization “js, controller”
-- slightly better scroll to item
-- change view files structure
-- make file-box smaller on mobile
-- update read me
-- update wiki
-- update resources
diff --git a/logs/v2.3.8.txt b/logs/v2.3.8.txt
new file mode 100644
index 0000000..0d6d7cb
--- /dev/null
+++ b/logs/v2.3.8.txt
@@ -0,0 +1,10 @@
+- fix “select + click” for search
+- add support for zip progress
+- new styling for path breadcrumb on mobile
+- add animation for breadcrumbs
+- fix local-storage toolbar changing on its own
+- some cleanup to the controller
+
+- update assets
+- update db file
+- update language file
\ No newline at end of file
diff --git a/src/Controllers/MediaController.php b/src/Controllers/MediaController.php
index bbc86d4..0227311 100755
--- a/src/Controllers/MediaController.php
+++ b/src/Controllers/MediaController.php
@@ -11,33 +11,39 @@ class MediaController extends Controller
{
use OpsTrait;
+ // main
protected $fileSystem;
protected $storageDisk;
protected $ignoreFiles;
protected $fileChars;
protected $folderChars;
protected $sanitizedText;
- protected $unallowed_mimes;
+ protected $unallowedMimes;
protected $LMF;
- protected $locked_files_list;
- protected $disks;
+ // extra
+ protected $storageDiskInfo;
+ protected $lockedList;
+ protected $cacheStore;
+ protected $db;
public function __construct()
{
$config = config('mediaManager');
- $this->fileSystem = array_get($config, 'storage_disk');
- $this->storageDisk = app('filesystem')->disk($this->fileSystem);
- $this->ignoreFiles = array_get($config, 'ignore_files');
- $this->fileChars = array_get($config, 'allowed_fileNames_chars');
- $this->folderChars = array_get($config, 'allowed_folderNames_chars');
- $this->sanitizedText = array_get($config, 'sanitized_text');
- $this->unallowed_mimes = array_get($config, 'unallowed_mimes');
- $this->LMF = array_get($config, 'last_modified_format');
-
- $this->locked_files_list = array_get($config, 'locked_files_list');
- $this->disks = config("filesystems.disks.{$this->fileSystem}");
+ $this->fileSystem = array_get($config, 'storage_disk');
+ $this->storageDisk = app('filesystem')->disk($this->fileSystem);
+ $this->ignoreFiles = array_get($config, 'ignore_files');
+ $this->fileChars = array_get($config, 'allowed_fileNames_chars');
+ $this->folderChars = array_get($config, 'allowed_folderNames_chars');
+ $this->sanitizedText = array_get($config, 'sanitized_text');
+ $this->unallowedMimes = array_get($config, 'unallowed_mimes');
+ $this->LMF = array_get($config, 'last_modified_format');
+
+ $this->db = app('db')->connection('mediamanager');
+ $this->lockedList = $this->db->table('locked')->pluck('path');
+ $this->storageDiskInfo = config("filesystems.disks.{$this->fileSystem}");
+ $this->cacheStore = app('cache')->store('mediamanager');
}
/**
@@ -68,7 +74,7 @@ public function get_files(Request $request)
}
return response()->json([
- 'locked' => app('db')->connection('mediamanager')->table('locked')->pluck('path'),
+ 'locked' => $this->lockedList,
'files' => [
'path' => $folder,
'items' => $this->getData($folder),
@@ -121,7 +127,7 @@ public function upload(Request $request)
try {
// check for mime type
- if (str_contains($file_type, $this->unallowed_mimes)) {
+ if (str_contains($file_type, $this->unallowedMimes)) {
throw new Exception(trans('MediaManager::messages.not_allowed_file_ext', ['attr'=>$file_type]));
}
@@ -291,7 +297,7 @@ public function move_file(Request $request)
'size' => $file_size,
];
} else {
- $exc = array_get($this->disks, 'root')
+ $exc = array_get($this->storageDiskInfo, 'root')
? trans('MediaManager::messages.error_moving')
: trans('MediaManager::messages.error_moving_cloud');
@@ -334,7 +340,7 @@ public function move_file(Request $request)
} else {
$exc = trans('MediaManager::messages.error_moving');
- if ('folder' == $one['type'] && !array_get($this->disks, 'root')) {
+ if ('folder' == $one['type'] && !array_get($this->storageDiskInfo, 'root')) {
$exc = trans('MediaManager::messages.error_moving_cloud');
}
@@ -410,7 +416,7 @@ public function lock_file(Request $request)
{
$path = $request->path;
$state = $request->state;
- $db = app('db')->connection('mediamanager')->table('locked');
+ $db = $this->db->table('locked');
'locked' == $state
? $db->insert(['path'=>$path])
@@ -420,60 +426,136 @@ public function lock_file(Request $request)
}
/**
- * zip folders.
- *
- * @param Request $request [description]
- *
- * @return [type] [description]
+ * zip ops.
*/
public function folder_download(Request $request)
{
- $name = $request->name;
- $dir = "{$request->folders}/$name";
+ return $this->download(
+ $request->name,
+ $this->storageDisk->allFiles("{$request->folders}/$request->name"),
+ 'folder'
+ );
+ }
+
+ public function files_download(Request $request)
+ {
+ return $this->download(
+ $request->name . '-files',
+ json_decode($request->list, true),
+ 'files'
+ );
+ }
+
+ protected function download($name, $list, $type)
+ {
+ // track changes
+ $counter = 100 / count($list);
+ $store = $this->cacheStore;
+ $cache_name = $name;
+ $store->forever("$cache_name.progress", 0);
- return response()->stream(function () use ($name, $dir) {
+ return response()->stream(function () use ($name, $list, $type, $counter, $store, $cache_name) {
$zip = new ZipStream("$name.zip", [
'content_type' => 'application/octet-stream',
]);
- foreach ($this->storageDisk->allFiles($dir) as $file) {
- if ($streamRead = $this->storageDisk->readStream($file)) {
- $zip->addFileFromStream(pathinfo($file, PATHINFO_BASENAME), $streamRead);
+ foreach ($list as $file) {
+ if ('folder' == $type) {
+ $file_name = pathinfo($file, PATHINFO_BASENAME);
+ $streamRead = $this->storageDisk->readStream($file);
+ } else {
+ $file_name = $file['name'];
+ $streamRead = @fopen($file['path'], 'r');
+ }
+
+ if ($streamRead) {
+ $store->increment("$cache_name.progress", round($counter, 2));
+ $zip->addFileFromStream($file_name, $streamRead);
} else {
- die('Could not open stream for reading');
+ $store->forever("$cache_name.abort", $file_name);
+ die();
}
}
+ $store->forever("$cache_name.done", true);
$zip->finish();
});
}
/**
- * zip files.
- *
- * @param Request $request [description]
- *
- * @return [type] [description]
+ * zip progress update.
*/
- public function files_download(Request $request)
+ public function zip_progress(Request $request)
{
- $name = $request->name;
- $list = json_decode($request->list, true);
+ // stop execution
+ $start = time();
+ $maxExecution = ini_get('max_execution_time');
+ $sleep = array_get($this->storageDiskInfo, 'root') ? 0.5 : 1.5;
+ $close = false;
+
+ // params
+ $id = $request->header('last-event-id');
+ $name = $request->name;
+
+ // get changes
+ $store = $this->cacheStore;
+ $cache_name = $name;
+
+ return response()->stream(function () use ($start, $maxExecution, $close, $sleep, $store, $cache_name) {
+ while (!$close) {
+ // progress
+ $this->es_msg($store->get("$cache_name.progress"), 'progress');
+
+ // avoid server crash
+ if (time() >= $start + $maxExecution) {
+ $close = true;
+ $this->es_msg(null, 'exit');
+ $this->clearZipCache($store, $cache_name);
+ }
- return response()->stream(function () use ($name, $list) {
- $zip = new ZipStream("$name.zip", [
- 'content_type' => 'application/octet-stream',
- ]);
+ // abort
+ if ($store->has("$cache_name.abort")) {
+ $close = true;
+ $this->es_msg('Could not open "' . $store->get("$cache_name.abort") . '" stream for reading.', 'abort');
+ $this->clearZipCache($store, $cache_name);
+ }
- foreach ($list as $file) {
- if ($streamRead = fopen($file['path'], 'r')) {
- $zip->addFileFromStream($file['name'], $streamRead);
- } else {
- die('Could not open stream for reading');
+ // done
+ if ($store->has("$cache_name.done")) {
+ $close = true;
+ $this->es_msg(100, 'progress');
+ $this->es_msg('All Done', 'done');
+ $this->clearZipCache($store, $cache_name);
+ }
+
+ ob_flush();
+ flush();
+
+ // don't wait unnecessary
+ if (!$close) {
+ sleep($sleep);
}
}
+ }, 200, [
+ 'Content-Type' => 'text/event-stream', // needed for SSE to work
+ 'Cache-Control' => 'no-cache', // make sure we dont cache this response
+ 'X-Accel-Buffering' => 'no', // needed for while loop to work
+ 'Access-Control-Allow-Origin' => config('app.url'), // for cors
+ 'Access-Control-Expose-Headers' => '*', // for cors
+ 'Access-Control-Allow-Credentials' => true, // for cors
+ ]);
+ }
- $zip->finish();
- });
+ protected function es_msg($data = null, $event = null)
+ {
+ echo $event ? "event: $event\n" : ':';
+ echo $data ? 'data: ' . json_encode(['response' => $data]) . "\n\n" : ':';
+ }
+
+ protected function clearZipCache($store, $item)
+ {
+ $store->forget("$item.progress");
+ $store->forget("$item.done");
+ $store->forget("$item.abort");
}
}
diff --git a/src/Controllers/OpsTrait.php b/src/Controllers/OpsTrait.php
index 7998fef..d65c18c 100644
--- a/src/Controllers/OpsTrait.php
+++ b/src/Controllers/OpsTrait.php
@@ -120,10 +120,10 @@ protected function folderFiles($folder)
*/
protected function getFilePath($name)
{
- $disks = $this->disks;
- $url = $this->storageDisk->url($name);
- $dir = str_replace(array_get($disks, 'url'), '', $url);
- $root = array_get($disks, 'root');
+ $info = $this->storageDiskInfo;
+ $url = $this->storageDisk->url($name);
+ $dir = str_replace(array_get($info, 'url'), '', $url);
+ $root = array_get($info, 'root');
// for other disks without root ex."cloud"
if (!$root) {
diff --git a/src/MediaManagerServiceProvider.php b/src/MediaManagerServiceProvider.php
index ed2a6c6..ce372fa 100644
--- a/src/MediaManagerServiceProvider.php
+++ b/src/MediaManagerServiceProvider.php
@@ -43,6 +43,13 @@ protected function packagePublish()
'prefix' => '',
]]);
+ // caching for zip-stream
+ config(['cache.stores.mediamanager' => [
+ 'driver' => 'database',
+ 'table' => 'cache',
+ 'connection' => 'mediamanager',
+ ]]);
+
// public
$this->publishes([
__DIR__ . '/dist' => public_path('assets/vendor/MediaManager'),
diff --git a/src/MediaRoutes.php b/src/MediaRoutes.php
index d08f254..5bcb28d 100644
--- a/src/MediaRoutes.php
+++ b/src/MediaRoutes.php
@@ -22,6 +22,7 @@ public static function routes()
Route::post('rename_file', ['uses' => '\ctf0\MediaManager\Controllers\MediaController@rename_file', 'as' => 'rename_file']);
Route::post('lock_file', ['uses' => '\ctf0\MediaManager\Controllers\MediaController@lock_file', 'as' => 'lock_file']);
+ Route::get('zip_progress/{name?}', ['uses' => '\ctf0\MediaManager\Controllers\MediaController@zip_progress', 'as' => 'zip_progress']);
Route::post('folder_download', ['uses' => '\ctf0\MediaManager\Controllers\MediaController@folder_download', 'as' => 'folder_download']);
Route::post('files_download', ['uses' => '\ctf0\MediaManager\Controllers\MediaController@files_download', 'as' => 'files_download']);
});
diff --git a/src/database/MediaManager.sqlite b/src/database/MediaManager.sqlite
index fbb18c6..ebdb212 100644
Binary files a/src/database/MediaManager.sqlite and b/src/database/MediaManager.sqlite differ
diff --git a/src/resources/assets/js/components/media.vue b/src/resources/assets/js/components/media.vue
index 08295c0..5288983 100644
--- a/src/resources/assets/js/components/media.vue
+++ b/src/resources/assets/js/components/media.vue
@@ -33,6 +33,7 @@ export default {
'filesRoute',
'dirsRoute',
'lockFileRoute',
+ 'zipProgressRoute',
'restrictPath',
'uploadPanelImgList',
'hideExt',
@@ -118,10 +119,10 @@ export default {
let ls = this.$ls.get('mediamanager')
if (ls) {
- this.randomNames = ls.randomNames == 'undefined' ? false : ls.randomNames
- this.folders = ls.folders == 'undefined' ? [] : ls.folders
- this.toolBar = ls.toolBar == 'undefined' ? true : ls.toolBar
- this.selectedFile = ls.selectedFileName == 'undefined' ? null : ls.selectedFileName
+ this.randomNames = ls.randomNames === undefined ? false : ls.randomNames
+ this.folders = ls.folders === undefined ? [] : ls.folders
+ this.toolBar = ls.toolBar === undefined ? true : ls.toolBar
+ this.selectedFile = ls.selectedFileName === undefined ? null : ls.selectedFileName
}
},
diff --git a/src/resources/assets/js/components/mixins/download.js b/src/resources/assets/js/components/mixins/download.js
new file mode 100644
index 0000000..6106403
--- /dev/null
+++ b/src/resources/assets/js/components/mixins/download.js
@@ -0,0 +1,87 @@
+export default {
+ methods: {
+ saveFile(item) {
+ if (this.isBulkSelecting()) {
+ this.bulkList.forEach((e) => {
+ if (e.type == 'folder') {
+ return this.showNotif(this.trans('sep_download'), 'warning')
+ }
+ downloadFile(e.path)
+ })
+
+ this.$refs['success-audio'].play()
+ return this.showNotif('All Done')
+ }
+
+ downloadFile(item.path)
+ return this.showNotif(`"${item.name}" ${this.trans('downloaded')}`)
+ },
+ hasFolder() {
+ return this.bulkList.some((e) => {
+ return e.type == 'folder'
+ })
+ },
+
+ ZipDownload(type) {
+ this.showProgress = true
+
+ // de-select download btn
+ this.$refs['zip'].forEach((e) => {
+ e.blur()
+ })
+
+ let folders = this.folders
+ let name = type == 'folder'
+ ? this.selectedFile.name
+ : folders.length ? `${folders[folders.length - 1]}-files` : 'media_manager-files'
+
+ let es = new EventSource(
+ `${this.zipProgressRoute}/${name}`,
+ {withCredentials: true}
+ )
+
+ // events
+ es.addEventListener('progress', (e) => {
+ this.progressCounter = `${this.getESData(e)}%`
+ }, false)
+
+ es.addEventListener('abort', (e) => {
+ this.showNotif(this.getESData(e), 'danger')
+ this.hideProgress(es)
+ }, false)
+
+ es.addEventListener('done', (e) => {
+ this.showNotif(this.getESData(e))
+ setTimeout(() => {
+ this.hideProgress(es)
+ }, 1000)
+ }, false)
+
+ es.addEventListener('exit', () => {
+ console.warn('Error: script took too long, listener terminated')
+ this.hideProgress(es)
+ }, false)
+
+ // error
+ es.addEventListener('error', (e) => {
+ if (e.readyState == EventSource.CLOSED) {
+ this.hideProgress(es)
+ console.error(`Error: connection terminated, ${EventSource}`)
+ }
+ }, false)
+ },
+ getESData(e, item = 'response') {
+ let data = JSON.parse(e.data)
+
+ return item ? data[item] : data
+ },
+ hideProgress(es) {
+ es.close()
+ this.progressCounter = 0
+ this.showProgress = false
+ this.toggleInfo = true
+ this.toggleLoading()
+ this.loadingFiles('hide')
+ }
+ }
+}
diff --git a/src/resources/assets/js/components/mixins/form.js b/src/resources/assets/js/components/mixins/form.js
index 9ca59e8..65991b2 100644
--- a/src/resources/assets/js/components/mixins/form.js
+++ b/src/resources/assets/js/components/mixins/form.js
@@ -1,4 +1,7 @@
+import Download from './download'
+
export default {
+ mixins: [Download],
methods: {
/* Main */
getFiles(folders = '/', prev_folder = null, prev_file = null) {
@@ -58,27 +61,25 @@ export default {
this.selectFirst()
}
- // check for prev opened folder
- if (prev_folder) {
- this.$nextTick(() => {
+ this.$nextTick(() => {
+ // check for prev opened folder
+ if (prev_folder) {
this.files.items.some((e, i) => {
if (e.name == prev_folder) {
return this.setSelected(e, i)
}
})
- })
- }
+ }
- // check for prev selected file
- if (prev_file) {
- this.$nextTick(() => {
+ // check for prev selected file
+ if (prev_file) {
this.files.items.some((e, i) => {
if (e.name == prev_file) {
return this.setSelected(e, i)
}
})
- })
- }
+ }
+ })
// we have files
if (this.allItemsCount) {
@@ -86,19 +87,17 @@ export default {
this.loadingFiles('hide')
this.toggleInfo = true
- // scroll to prev selected item
- setTimeout(() => {
+ this.$nextTick(() => {
+ // scroll to prev selected item
if (this.currentFileIndex) {
this.scrollToFile(this.$refs[`file_${this.currentFileIndex}`])
}
- }, 800)
- // scroll to breadcrumb item
- setTimeout(() => {
+ // scroll to breadcrumb item
let name = folders.split('/').pop()
- let count = document.getElementById(`${name ? name : 'home'}-bc`).offsetLeft
- this.$refs.bc.scrollBy({top: 0, left: count, behavior: 'smooth'})
- }, 100)
+ let count = document.getElementById(`${name ? name : 'library'}-bc`).offsetLeft
+ this.$refs.bc.$el.scrollBy({top: 0, left: count, behavior: 'smooth'})
+ })
return this.updateDirsList()
}
@@ -389,7 +388,7 @@ export default {
if (this.filteredItemsCount) {
this.filterdList.some((e) => {
- if (e.name == destination) {
+ if (e.type == 'folder' && e.name == destination) {
e.items += parseInt(count)
e.size += parseInt(weight)
}
@@ -397,7 +396,7 @@ export default {
}
this.files.items.some((e) => {
- if (e.name == destination) {
+ if (e.type == 'folder' && e.name == destination) {
e.items += parseInt(count)
e.size += parseInt(weight)
}
diff --git a/src/resources/assets/js/components/mixins/selected.js b/src/resources/assets/js/components/mixins/selected.js
index 68e71fe..eb15310 100644
--- a/src/resources/assets/js/components/mixins/selected.js
+++ b/src/resources/assets/js/components/mixins/selected.js
@@ -15,17 +15,41 @@ export default {
if (e && e.shiftKey) {
this.bulkSelect = true
- // normal
+ // forward
let begin = this.currentFileIndex
- let end = index + 1
+ let end = index
+ let dir = 'forward'
- // reverse
+ // backward
if (begin > index) {
begin = index
- end = this.currentFileIndex + 1
+ end = this.currentFileIndex
+ dir = 'backward'
}
- return this.bulkList = this.allFiles.slice(begin, end)
+ // search
+ if (this.searchFor) {
+ this.bulkList = []
+ let indexList = this.getRange(begin, end)
+
+ indexList.map((i) => {
+ this.$refs[`file_${i}`][0].click()
+ })
+
+ // to have the same expected pattern as normal shift + click
+ if (dir == 'forward') {
+ this.selectedFile = this.bulkList[0]
+ this.currentFileIndex = indexList[0]
+ } else {
+ this.selectedFile = this.bulkList[this.bulkItemsCount - 1]
+ this.currentFileIndex = indexList[indexList.length - 1]
+ }
+
+ return
+ }
+
+ // default
+ return this.bulkList = this.allFiles.slice(begin, end + 1)
}
// normal selection
@@ -37,6 +61,9 @@ export default {
this.pushtoBulkList(file)
}
},
+ getRange(start, end) {
+ return Array(end - start + 1).fill().map((_, idx) => start + idx)
+ },
selectedFileIs(val) {
if (this.selectedFile !== null) {
return this.fileTypeIs(this.selectedFile, val)
diff --git a/src/resources/assets/js/components/mixins/utils.js b/src/resources/assets/js/components/mixins/utils.js
index 66bb14f..11db75a 100644
--- a/src/resources/assets/js/components/mixins/utils.js
+++ b/src/resources/assets/js/components/mixins/utils.js
@@ -179,20 +179,6 @@ export default {
this.linkCopied = true
this.$copyText(path)
},
- // download
- saveFile(item) {
- if (this.isBulkSelecting()) {
- this.bulkList.forEach((e) => {
- downloadFile(e.path)
- })
-
- manager.$refs['success-audio'].play()
- return this.showNotif('All Done')
- }
-
- downloadFile(item.path)
- return this.showNotif(`"${item.name}" ${this.trans('downloaded')}`)
- },
// ls
updateLs(obj) {
diff --git a/src/resources/assets/js/manager.js b/src/resources/assets/js/manager.js
index 1c1a1de..f705b8c 100644
--- a/src/resources/assets/js/manager.js
+++ b/src/resources/assets/js/manager.js
@@ -54,7 +54,7 @@ import 'vue-awesome/icons/shopping-basket'
import 'vue-awesome/icons/folder'
import 'vue-awesome/icons/refresh'
import 'vue-awesome/icons/share'
-import 'vue-awesome/icons/i-cursor'
+import 'vue-awesome/icons/terminal'
import 'vue-awesome/icons/trash'
import 'vue-awesome/icons/minus'
import 'vue-awesome/icons/plus'
diff --git a/src/resources/assets/sass/extra/vars.scss b/src/resources/assets/sass/extra/vars.scss
index 6a01529..86d0683 100644
--- a/src/resources/assets/sass/extra/vars.scss
+++ b/src/resources/assets/sass/extra/vars.scss
@@ -19,4 +19,4 @@ $red: hsl(348, 100%, 61%);
$blue: hsl(217, 71%, 53%);
$shadow_1: 0 10px 45px 0 rgba($black, 0.2);
$shadow_2: 0 6px 25px 0 rgba($black, 0.3);
-$shadow_3: 0 6px 20px rgba($black, 0.08);
+$shadow_3: 0 6px 10px rgba($black, 0.08);
diff --git a/src/resources/assets/sass/media.scss b/src/resources/assets/sass/media.scss
index eb39e0e..e5156e2 100644
--- a/src/resources/assets/sass/media.scss
+++ b/src/resources/assets/sass/media.scss
@@ -124,41 +124,81 @@
overflow: scroll;
align-items: center;
width: 100%;
- padding: 1rem 0;
+ padding: 1rem 0 2rem;
list-style: none;
+ transition: all 0.25s ease-in-out;
li {
+ position: relative;
flex: 1;
margin-right: 1rem;
+ padding: 2px;
text-align: center;
+ border: 1px dashed darken($active_theme, 2%);
+ border-radius: 5px;
- a {
- display: block;
+ // ---
+ &::after {
+ position: absolute;
+ top: 50%;
+ right: -1rem;
+ width: 1rem;
+ content: '';
+ border-top: 1px dashed darken($active_theme, 2%);
+ }
+
+ &:last-of-type {
+ margin-right: 0;
+ margin-left: 1px;
+ padding-right: 2rem;
+
+ &::after {
+ display: none;
+ }
+
+ // get around vue not animating items
+ // because of changeing border style
+ &::before {
+ position: absolute;
+ top: -1px;
+ right: -1px;
+ bottom: -1px;
+ left: 15%;
+ content: '';
+ border: 1px solid $white;
+ border-left: none;
+ border-radius: 0 5px 5px 0;
+ }
+ }
+
+ // ---•
+ &:nth-last-of-type(2)::before {
+ font-size: 1.8rem;
+ position: absolute;
+ z-index: 1;
+ top: 0.65rem;
+ right: -1.57rem;
+ content: '•';
+ color: darken($active_theme, 2%);
}
a,
- &:only-of-type {
+ p {
+ display: block;
padding: 1rem;
- transition: all 0.3s ease-in-out;
white-space: nowrap;
- color: $blue;
- border: 1px solid lighten($active_theme, 2%);
border-radius: 5px;
background: $white;
-
- &:hover {
- border-color: transparent;
- box-shadow: $shadow_3;
- }
}
- &:only-of-type {
- display: none;
- }
+ a {
+ transition: all 0.25s ease-in-out;
+ color: $blue;
+ box-shadow: $shadow_3;
- &:last-of-type {
- margin-right: 0;
- padding-right: 3rem;
+ &:hover {
+ box-shadow: none;
+ }
}
}
}
@@ -427,6 +467,7 @@
overflow: hidden;
text-align: center;
color: darken($active_theme, 50%);
+ border-bottom: 1px dashed darken($active_theme, 5%);
.__sidebar-none-selected {
display: flex;
@@ -475,10 +516,6 @@
&:not(.__sidebar-count) {
flex: 1;
- &:not(:empty) {
- border-top: 1px solid darken($active_theme, 5%);
- }
-
h4 {
font-size: 1rem;
margin-bottom: 0.1em;
@@ -549,8 +586,7 @@
/* modal */
.__modal-preview {
- align-items: center;
- padding: 0.7rem;
+ padding: 0.7rem 0.7rem 0;
* {
color: $black;
@@ -735,18 +771,23 @@
padding: 0;
cursor: pointer;
vertical-align: bottom;
+ color: darken($active_theme, 70%);
border: none;
border-radius: 0;
background: transparent;
- * {
- color: darken($active_theme, 70%);
- }
-
&:focus {
border: none;
box-shadow: none !important;
}
+
+ &:disabled {
+ cursor: not-allowed;
+
+ * {
+ color: darken($active_theme, 20%);
+ }
+ }
}
a[target='_blank'] {
@@ -811,25 +852,31 @@ a[target='_blank'] {
}
.modal {
+ overflow: scroll;
align-items: flex-start;
- &.is-active {
- padding-top: 4%;
+ .modal-background {
+ position: fixed;
}
-}
-.modal-card {
- margin: 0;
- padding: 1rem;
-}
+ .modal-card {
+ margin: 0;
+ padding: 1rem;
+ }
-.modal-content {
- box-shadow: $shadow_1;
-}
+ .modal-content {
+ box-shadow: $shadow_1;
+ }
-.modal-card-foot {
- justify-content: flex-end;
- background-color: $white;
+ .modal-card-foot {
+ justify-content: flex-end;
+ background-color: $white;
+ }
+
+ &.is-active {
+ margin-bottom: 2%;
+ padding-top: 4%;
+ }
}
.image {
diff --git a/src/resources/lang/en/messages.php b/src/resources/lang/en/messages.php
index d489609..cdbfc4f 100644
--- a/src/resources/lang/en/messages.php
+++ b/src/resources/lang/en/messages.php
@@ -3,7 +3,7 @@
return array (
'add_folder' => 'Add Folder',
'add_new_folder' => 'Add New Folder',
- 'ajax_error' => 'Oh NO! Something Went Wrong',
+ 'ajax_error' => 'Oh NO! Something Went Wrong.',
'are_you_sure_delete' => 'Are you sure you want to delete ?',
'audio_support' => 'Your browser does not support the audio element.',
'bulk_select' => 'Bulk Select',
@@ -11,6 +11,7 @@
'clear' => 'Clear :attr',
'close' => 'Close',
'copied' => 'Copied',
+ 'copy' => 'Copy',
'copy_file_folder' => 'Copy File/Folder',
'copy_files' => 'Copy Files Instead ?',
'copy_success' => 'Successfully Copied',
@@ -18,7 +19,7 @@
'create_new_folder' => 'Create New Folder',
'create_success' => 'Successfully Created',
'delete' => 'Delete',
- 'delete_confirm' => 'Yes, Delete it!',
+ 'delete_confirm' => 'Yes, Delete it !',
'delete_folder' => 'Deleting a folder will remove all files and folders contained inside.',
'delete_success' => 'Successfully Deleted',
'destination_folder' => 'Destination Folder',
@@ -26,10 +27,11 @@
'download_folder' => 'Download Folder',
'downloaded' => 'Downloaded',
'error_already_exists' => 'A File/Folder already exists with that name.',
- 'error_creating_dir' => 'Something seems to have gone wrong with creating the directory, please check your permissions,',
- 'error_deleting_file' => 'Something seems to have gone wrong deleting this file / folder, please check your permissions,',
+ 'error_creating_dir' => 'Something gone wrong while creating the directory, please check your permissions,',
+ 'error_deleting_file' => 'Something gone wrong while deleting this file / folder, please check your permissions,',
'error_doesnt_exist' => 'Folder ":attr" Doesnt Exist',
- 'error_moving' => 'There seems to be a problem moving that file / folder, make sure you have the correct permissions.',
+ 'error_moving' => 'There seems to be a problem moving this file / folder, make sure you have the correct permissions.',
+ 'error_moving_cloud' => 'Cloud Folders can\'t be "Renamed, Moved or Copied".',
'filter_by' => 'Filter By :attr',
'find' => 'Find',
'found' => 'Found',
@@ -59,6 +61,7 @@
'select_all' => 'Select All',
'select_non' => 'Select Non',
'selected' => 'Selected',
+ 'sep_download' => 'Folders Should Be Downloaded Separately.',
'single_char_folder' => 'Folders With First Level Path As Single Character Should Be Avoided',
'size' => 'Size',
'sort_by' => 'Sort By',
@@ -71,9 +74,6 @@
'upload' => 'Upload',
'upload_success' => 'Successfully Uploaded',
'upload_text' => 'Drag & Drop Files
Or
Click To Upload',
- 'url' => 'URL',
'use_random_names' => 'Use Random Names ?',
'video_support' => 'Your browser does not support the video tag.',
- 'copy' => 'Copy',
- 'error_moving_cloud' => 'Cloud Folders can\'t be "Renamed / Moved or Copied".',
);
\ No newline at end of file
diff --git a/src/resources/views/_manager.blade.php b/src/resources/views/_manager.blade.php
index a0cdfe1..d80c892 100644
--- a/src/resources/views/_manager.blade.php
+++ b/src/resources/views/_manager.blade.php
@@ -17,17 +17,19 @@
'no_val' => trans('MediaManager::messages.no_val'),
'single_char_folder' => trans('MediaManager::messages.single_char_folder'),
'downloaded' => trans('MediaManager::messages.downloaded'),
+ 'sep_download' => trans('MediaManager::messages.sep_download'),
'upload_success' => trans('MediaManager::messages.upload_success'),
'create_success' => trans('MediaManager::messages.create_success'),
'rename_success' => trans('MediaManager::messages.rename_success'),
'move_success' => trans('MediaManager::messages.move_success'),
'delete_success' => trans('MediaManager::messages.delete_success'),
- 'copy_success' => trans('MediaManager::messages.copy_success')
+ 'copy_success' => trans('MediaManager::messages.copy_success'),
]) }}"
:upload-panel-img-list="{{ $patterns }}"
files-route="{{ route('media.files') }}"
dirs-route="{{ route('media.directories') }}"
lock-file-route="{{ route('media.lock_file') }}"
+ zip-progress-route="{{ route('media.zip_progress') }}"
:restrict-path="{{ isset($path) ? $path : 'null' }}">