Merge remote-tracking branch 'origin/master' into oasis

# Conflicts:
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js
#	public/chunks/app-language.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js
#	public/chunks/homepage.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/page-edit.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/profile.js
#	public/chunks/profile~chunks/settings-password.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/shared-files.js
#	public/chunks/shared.js
#	public/chunks/shared/file-browser.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade-plan.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
#	public/vendors~chunks/platform~chunks/shared.js
This commit is contained in:
Peter Papp
2021-04-20 08:15:34 +02:00
154 changed files with 5332 additions and 4857 deletions

View File

@@ -59,6 +59,7 @@ class BrowseShareController extends Controller
}
return view("index")
->with('installation', 'setup-done')
->with('settings', get_settings_in_json() ?? null);
}

View File

@@ -10,6 +10,7 @@ use App\Models\LanguageTranslation;
use ByteUnits\Metric;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\QueryException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
@@ -851,11 +852,20 @@ function __t($key, $values = null)
{
// Get current locale
$locale = cache()->rememberForever('language', function () {
return get_setting('language') ?? 'en';
try {
return get_setting('language') ?? 'en';
} catch (QueryException $e) {
return 'en';
}
});
// Get language strings
$strings = cache()->rememberForever("language-translations-$locale", function () use ($locale) {
return Language::whereLocale($locale)->first()->languageTranslations ?? get_default_language_translations();
try {
return Language::whereLocale($locale)->first()->languageTranslations ?? get_default_language_translations();
} catch (QueryException $e) {
return get_default_language_translations();
}
});
// Find the string by key

View File

@@ -333,17 +333,13 @@ class FileManagerService
if ($item['type'] === 'folder') {
Folder::find($item['id'])
->update([
'parent_id' => $to_id
]);
->update(['parent_id' => $to_id]);
}
// Move file
if ($item['type'] !== 'folder') {
UserFile::find($item['id'])
->update([
'folder_id' => $to_id
]);
->update(['folder_id' => $to_id]);
}
}
}

View File

@@ -90,8 +90,6 @@ return [
"admin_settings.tabs.payments" => "Payments",
"global.monthly_ac" => "Mo.",
"global.premium" => "Premium",
"global.saas" => "Services",
"global.subscription" => "Subscription",
"global.upgrade_plan" => "Upgrade Plan",
"incomplete_payment.description" => "Your latest payment is incomplete. {0}",
"incomplete_payment.href" => "Please confirm your payment.",
@@ -380,7 +378,6 @@ return [
"global.free" => "Free",
"global.get_it" => "Get It",
"global.incomplete" => "Incomplete",
"global.menu" => "Menu",
"global.or" => "or",
"global.total" => "Total",
"input_image.supported" => "Supported formats are .png, .jpg, .jpeg.",
@@ -540,9 +537,7 @@ return [
"routes_title.page_edit" => "Edit Page",
"routes_title.pages" => "Pages",
"routes_title.profile" => "My Profile",
"routes_title.profile_settings" => "Profile Settings",
"routes_title.settings" => "Settings",
"routes_title.settings_mobile" => "Settings",
"routes_title.settings_password" => "Change Password",
"routes_title.settings_storage" => "Storage",
"routes_title.user_create" => "Create User",
@@ -677,5 +672,6 @@ return [
'og_image_description' => 'Image that appear when someone shares the content to Facebook or any other social medium. Preferred size is 1200x627',
'app_touch_icon' => 'App Touch Icon',
'app_touch_icon_description' => 'If user store bookmark on his phone screen, this icon appear in app thumbnail. Preferred size is 156x156',
'select_search_placeholder' => 'Search in list...',
]
];

2081
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
"@fortawesome/vue-fontawesome": "^0.1.10",
"lodash": "^4.17.20",
"node-sass": "^4.14.1",
"pdfvuer": "^1.7.5",
"twemoji": "^13.0.1",
"vee-validate": "^3.3.9",
"vue": "^2.6.11",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{BLAx:function(n,t,a){var e=a("hGkI");"string"==typeof e&&(e=[[n.i,e,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};a("aET+")(e,o);e.locals&&(n.exports=e.locals)},"c/uq":function(n,t,a){"use strict";var e=a("BLAx");a.n(e).a},hGkI:function(n,t,a){(n.exports=a("I1BE")(!1)).push([n.i,".auth-logo-text[data-v-23099f18] {\n font-size: 1.375em;\n font-weight: 800;\n margin-bottom: 40px;\n display: block;\n}\n.auth-form[data-v-23099f18] {\n text-align: center;\n max-width: 600px;\n padding: 25px 20px;\n display: table-cell;\n vertical-align: middle;\n}\n.auth-form input[data-v-23099f18] {\n min-width: 310px;\n}\n.auth-form .additional-link a[data-v-23099f18] {\n font-weight: 700;\n text-decoration: none;\n}\n.auth-form .user-avatar[data-v-23099f18] {\n width: 100px;\n height: 100px;\n -o-object-fit: cover;\n object-fit: cover;\n margin-bottom: 20px;\n border-radius: 8px;\n box-shadow: 0 10px 30px rgba(25, 54, 60, 0.2);\n}\n.auth-form .logo[data-v-23099f18] {\n width: 120px;\n margin-bottom: 20px;\n}\n.auth-form h1[data-v-23099f18] {\n font-size: 2.125em;\n font-weight: 800;\n line-height: 1.2;\n margin-bottom: 2px;\n color: #1B2539;\n}\n.auth-form h2[data-v-23099f18] {\n font-size: 1.4375em;\n font-weight: 500;\n margin-bottom: 50px;\n color: #1B2539;\n}\n.auth-form .block-form[data-v-23099f18] {\n margin-left: auto;\n margin-right: auto;\n}\n@media only screen and (min-width: 690px) and (max-width: 960px) {\n.auth-form[data-v-23099f18] {\n padding-left: 20%;\n padding-right: 20%;\n}\n}\n@media only screen and (max-width: 690px) {\n.auth-form[data-v-23099f18] {\n width: 100%;\n}\n.auth-form h1[data-v-23099f18] {\n font-size: 1.875em;\n}\n.auth-form h2[data-v-23099f18] {\n font-size: 1.3125em;\n}\n}\n@media only screen and (max-width: 490px) {\n.auth-form h1[data-v-23099f18] {\n font-size: 1.375em;\n}\n.auth-form h2[data-v-23099f18] {\n font-size: 1.125em;\n}\n.auth-form input[data-v-23099f18] {\n min-width: initial;\n}\n.auth-form .additional-link[data-v-23099f18] {\n font-size: 0.9375em;\n}\n}\n@media (prefers-color-scheme: dark) {\n.auth-form h1[data-v-23099f18], .auth-form h2[data-v-23099f18], .auth-form .additional-link[data-v-23099f18] {\n color: #bec6cf;\n}\n}\n",""])},pAWr:function(n,t,a){"use strict";a.r(t);var e=a("bDRN"),o=a("A5+z"),r=a("j8qy"),i=a("ASoH"),f=a("TJPC"),d=a("L2JU");a("vDqi");function s(n,t){var a=Object.keys(n);if(Object.getOwnPropertySymbols){var e=Object.getOwnPropertySymbols(n);t&&(e=e.filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable}))),a.push.apply(a,e)}return a}function c(n,t,a){return t in n?Object.defineProperty(n,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):n[t]=a,n}var p={name:"NotFound",components:{AuthContentWrapper:e.a,ValidationProvider:o.ValidationProvider,ValidationObserver:o.ValidationObserver,AuthContent:r.a,AuthButton:i.a,required:f.a},computed:function(n){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?s(Object(a),!0).forEach((function(t){c(n,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(a)):s(Object(a)).forEach((function(t){Object.defineProperty(n,t,Object.getOwnPropertyDescriptor(a,t))}))}return n}({},Object(d.b)(["config"])),data:function(){return{isLoading:!1}}},u=(a("c/uq"),a("KHd+")),h=Object(u.a)(p,(function(){var n=this,t=n.$createElement,a=n._self._c||t;return a("AuthContentWrapper",{ref:"auth"},[a("AuthContent",{attrs:{name:"not-found",visible:!0}},[n.config.app_logo?a("img",{staticClass:"logo",attrs:{src:n.$getImage(n.config.app_logo),alt:n.config.app_name}}):n._e(),n._v(" "),n.config.app_logo?n._e():a("b",{staticClass:"auth-logo-text"},[n._v(n._s(n.config.app_name))]),n._v(" "),a("h1",[n._v(n._s(n.$t("page_shared_404.title")))]),n._v(" "),a("h2",[n._v(n._s(n.$t("page_shared_404.subtitle")))]),n._v(" "),a("span",{staticClass:"additional-link"},[n._v(n._s(n.$t("page_registration.have_an_account"))+"\n "),a("router-link",{attrs:{to:{name:"SignIn"}}},[n._v("\n "+n._s(n.$t("page_forgotten_password.password_remember_button"))+"\n ")])],1)])],1)}),[],!1,null,"23099f18",null);t.default=h.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{BLAx:function(n,t,a){var e=a("hGkI");"string"==typeof e&&(e=[[n.i,e,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};a("aET+")(e,o);e.locals&&(n.exports=e.locals)},"c/uq":function(n,t,a){"use strict";var e=a("BLAx");a.n(e).a},hGkI:function(n,t,a){(n.exports=a("I1BE")(!1)).push([n.i,".auth-logo-text[data-v-23099f18] {\n font-size: 1.375em;\n font-weight: 800;\n margin-bottom: 40px;\n display: block;\n}\n.auth-form[data-v-23099f18] {\n text-align: center;\n max-width: 600px;\n padding: 25px 20px;\n display: table-cell;\n vertical-align: middle;\n}\n.auth-form input[data-v-23099f18] {\n min-width: 310px;\n}\n.auth-form .additional-link a[data-v-23099f18] {\n font-weight: 700;\n text-decoration: none;\n}\n.auth-form .user-avatar[data-v-23099f18] {\n width: 100px;\n height: 100px;\n -o-object-fit: cover;\n object-fit: cover;\n margin-bottom: 20px;\n border-radius: 8px;\n box-shadow: 0 10px 30px rgba(25, 54, 60, 0.2);\n}\n.auth-form .logo[data-v-23099f18] {\n width: 120px;\n margin-bottom: 20px;\n}\n.auth-form h1[data-v-23099f18] {\n font-size: 2.125em;\n font-weight: 800;\n line-height: 1.2;\n margin-bottom: 2px;\n color: #1B2539;\n}\n.auth-form h2[data-v-23099f18] {\n font-size: 1.4375em;\n font-weight: 500;\n margin-bottom: 50px;\n color: #1B2539;\n}\n.auth-form .block-form[data-v-23099f18] {\n margin-left: auto;\n margin-right: auto;\n}\n@media only screen and (min-width: 690px) and (max-width: 960px) {\n.auth-form[data-v-23099f18] {\n padding-left: 20%;\n padding-right: 20%;\n}\n}\n@media only screen and (max-width: 690px) {\n.auth-form[data-v-23099f18] {\n width: 100%;\n}\n.auth-form h1[data-v-23099f18] {\n font-size: 1.875em;\n}\n.auth-form h2[data-v-23099f18] {\n font-size: 1.3125em;\n}\n}\n@media only screen and (max-width: 490px) {\n.auth-form h1[data-v-23099f18] {\n font-size: 1.375em;\n}\n.auth-form h2[data-v-23099f18] {\n font-size: 1.125em;\n}\n.auth-form input[data-v-23099f18] {\n min-width: initial;\n}\n.auth-form .additional-link[data-v-23099f18] {\n font-size: 0.9375em;\n}\n}\n@media (prefers-color-scheme: dark) {\n.auth-form h1[data-v-23099f18], .auth-form h2[data-v-23099f18], .auth-form .additional-link[data-v-23099f18] {\n color: #bec6cf;\n}\n}\n",""])},pAWr:function(n,t,a){"use strict";a.r(t);var e=a("bDRN"),o=a("A5+z"),r=a("j8qy"),i=a("ASoH"),f=a("TJPC"),d=a("L2JU");a("vDqi");function s(n,t){var a=Object.keys(n);if(Object.getOwnPropertySymbols){var e=Object.getOwnPropertySymbols(n);t&&(e=e.filter((function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable}))),a.push.apply(a,e)}return a}function c(n,t,a){return t in n?Object.defineProperty(n,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):n[t]=a,n}var p={name:"NotFound",components:{AuthContentWrapper:e.a,ValidationProvider:o.ValidationProvider,ValidationObserver:o.ValidationObserver,AuthContent:r.a,AuthButton:i.a,required:f.a},computed:function(n){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?s(Object(a),!0).forEach((function(t){c(n,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(a)):s(Object(a)).forEach((function(t){Object.defineProperty(n,t,Object.getOwnPropertyDescriptor(a,t))}))}return n}({},Object(d.b)(["config"])),data:function(){return{isLoading:!1}}},u=(a("c/uq"),a("KHd+")),h=Object(u.a)(p,(function(){var n=this,t=n.$createElement,a=n._self._c||t;return a("AuthContentWrapper",{ref:"auth"},[a("AuthContent",{attrs:{name:"not-found",visible:!0}},[n.config.app_logo?a("img",{staticClass:"logo",attrs:{src:n.$getImage(n.config.app_logo),alt:n.config.app_name}}):n._e(),n._v(" "),n.config.app_logo?n._e():a("b",{staticClass:"auth-logo-text"},[n._v(n._s(n.config.app_name))]),n._v(" "),a("h1",[n._v(n._s(n.$t("page_shared_404.title")))]),n._v(" "),a("h2",[n._v(n._s(n.$t("page_shared_404.subtitle")))]),n._v(" "),a("span",{staticClass:"additional-link"},[n._v(n._s(n.$t("page_registration.have_an_account"))+"\n "),a("router-link",{attrs:{to:{name:"SignIn"}}},[n._v("\n "+n._s(n.$t("page_forgotten_password.password_remember_button"))+"\n ")])],1)])],1)}),[],!1,null,"23099f18",null);t.default=h.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[63],{"2wZp":function(t,e,n){"use strict";var i=n("Mlra");n.n(i).a},"6Rdq":function(t,e,n){"use strict";var i=n("9Q3x"),r=n("yMep"),o=n("c4kp"),s=n("2QtR"),a=n("L2JU"),c=n("xCqy");function l(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function p(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var u={name:"FilesView",components:{DesktopSortingAndPreview:i.a,DesktopToolbar:r.a,FileBrowser:o.a,ContextMenu:s.a},computed:function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?l(Object(n),!0).forEach((function(e){p(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}({},Object(a.b)(["config"])),methods:{contextMenu:function(t,e){c.a.$emit("contextMenu:show",t,e)}}},d=(n("2wZp"),n("KHd+")),f=Object(d.a)(u,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{attrs:{id:"files-view"},on:{"!contextmenu":function(e){return e.preventDefault(),t.contextMenu(e,void 0)}}},[n("ContextMenu"),t._v(" "),n("DesktopSortingAndPreview"),t._v(" "),n("DesktopToolbar"),t._v(" "),n("FileBrowser")],1)}),[],!1,null,null,null);e.a=f.exports},CoTS:function(t,e,n){"use strict";n.r(e);var i=n("6Rdq"),r=n("LtV2"),o=n("hXay"),s=n("CjXH"),a={name:"FilesView",components:{ContentFileView:i.a,ContentSidebar:r.a,ContentGroup:o.a,LinkIcon:s.G,UsersIcon:s.gb},methods:{getShared:function(){this.$store.dispatch("getShared",[{back:!1,init:!1}])},getParticipantUploads:function(){this.$store.dispatch("getParticipantUploads")}},mounted:function(){this.getShared()}},c=n("KHd+"),l=Object(c.a)(a,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{attrs:{id:"viewport"}},[n("ContentSidebar",[n("ContentGroup",{attrs:{title:t.$t("sidebar.locations_title")}},[n("div",{staticClass:"menu-list-wrapper vertical"},[n("li",{staticClass:"menu-list-item link",class:{"is-active":t.$isThisLocation(["shared"])},on:{click:function(e){return t.getShared()}}},[n("div",{staticClass:"icon text-theme"},[n("link-icon",{attrs:{size:"17"}})],1),t._v(" "),n("div",{staticClass:"label text-theme"},[t._v("\n "+t._s(t.$t("sidebar.my_shared"))+"\n ")])]),t._v(" "),n("li",{staticClass:"menu-list-item link",class:{"is-active":t.$isThisLocation(["participant_uploads"])},on:{click:function(e){return t.getParticipantUploads()}}},[n("div",{staticClass:"icon text-theme"},[n("users-icon",{attrs:{size:"17"}})],1),t._v(" "),n("div",{staticClass:"label text-theme"},[t._v("\n "+t._s(t.$t("sidebar.participant_uploads"))+"\n ")])])])])],1),t._v(" "),n("ContentFileView")],1)}),[],!1,null,"55043004",null);e.default=l.exports},Mlra:function(t,e,n){var i=n("Q8SN");"string"==typeof i&&(i=[[t.i,i,""]]);var r={hmr:!0,transform:void 0,insertInto:void 0};n("aET+")(i,r);i.locals&&(t.exports=i.locals)},Q8SN:function(t,e,n){(t.exports=n("I1BE")(!1)).push([t.i,"#files-view {\n font-family: 'Nunito', sans-serif;\n font-size: 16px;\n width: 100%;\n height: 100%;\n position: relative;\n min-width: 320px;\n overflow-x: hidden;\n padding-left: 15px;\n padding-right: 15px;\n overflow-y: hidden;\n}\n@media only screen and (max-width: 690px) {\n#files-view {\n padding-left: 0;\n padding-right: 0;\n}\n}\n",""])}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{"2wZp":function(t,e,n){"use strict";var i=n("Mlra");n.n(i).a},"6Rdq":function(t,e,n){"use strict";var i=n("9Q3x"),r=n("yMep"),o=n("c4kp"),s=n("2QtR"),a=n("L2JU"),c=n("xCqy");function l(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function p(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var d={name:"FilesView",components:{DesktopSortingAndPreview:i.a,DesktopToolbar:r.a,FileBrowser:o.a,ContextMenu:s.a},computed:function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?l(Object(n),!0).forEach((function(e){p(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}({},Object(a.b)(["config"])),methods:{contextMenu:function(t,e){c.a.$emit("contextMenu:show",t,e)}}},u=(n("2wZp"),n("KHd+")),f=Object(u.a)(d,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{attrs:{id:"files-view"},on:{"!contextmenu":function(e){return e.preventDefault(),t.contextMenu(e,void 0)}}},[n("ContextMenu"),t._v(" "),n("DesktopSortingAndPreview"),t._v(" "),n("DesktopToolbar"),t._v(" "),n("FileBrowser")],1)}),[],!1,null,null,null);e.a=f.exports},CoTS:function(t,e,n){"use strict";n.r(e);var i=n("6Rdq"),r=n("LtV2"),o=n("hXay"),s=n("CjXH"),a={name:"FilesView",components:{ContentFileView:i.a,ContentSidebar:r.a,ContentGroup:o.a,LinkIcon:s.H,UsersIcon:s.hb},methods:{getShared:function(){this.$store.dispatch("getShared",[{back:!1,init:!1}])},getParticipantUploads:function(){this.$store.dispatch("getParticipantUploads")}},mounted:function(){this.getShared()}},c=n("KHd+"),l=Object(c.a)(a,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{attrs:{id:"viewport"}},[n("ContentSidebar",[n("ContentGroup",{attrs:{title:t.$t("sidebar.locations_title")}},[n("div",{staticClass:"menu-list-wrapper vertical"},[n("li",{staticClass:"menu-list-item link",class:{"is-active":t.$isThisLocation(["shared"])},on:{click:t.getShared}},[n("div",{staticClass:"icon text-theme"},[n("link-icon",{attrs:{size:"17"}})],1),t._v(" "),n("div",{staticClass:"label text-theme"},[t._v("\n "+t._s(t.$t("sidebar.my_shared"))+"\n ")])]),t._v(" "),n("li",{staticClass:"menu-list-item link",class:{"is-active":t.$isThisLocation(["participant_uploads"])},on:{click:t.getParticipantUploads}},[n("div",{staticClass:"icon text-theme"},[n("users-icon",{attrs:{size:"17"}})],1),t._v(" "),n("div",{staticClass:"label text-theme"},[t._v("\n "+t._s(t.$t("sidebar.participant_uploads"))+"\n ")])])])])],1),t._v(" "),n("ContentFileView")],1)}),[],!1,null,"4b1985f4",null);e.default=l.exports},Mlra:function(t,e,n){var i=n("Q8SN");"string"==typeof i&&(i=[[t.i,i,""]]);var r={hmr:!0,transform:void 0,insertInto:void 0};n("aET+")(i,r);i.locals&&(t.exports=i.locals)},Q8SN:function(t,e,n){(t.exports=n("I1BE")(!1)).push([t.i,"#files-view {\n font-family: 'Nunito', sans-serif;\n font-size: 16px;\n width: 100%;\n height: 100%;\n position: relative;\n min-width: 320px;\n overflow-x: hidden;\n padding-left: 15px;\n padding-right: 15px;\n overflow-y: hidden;\n}\n@media only screen and (max-width: 690px) {\n#files-view {\n padding-left: 0;\n padding-right: 0;\n}\n}\n",""])}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/main.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,9 @@
/*!
* vue-router v3.4.3
* (c) 2020 Evan You
* @license MIT
*/
/*!
* Vue.js v2.6.11
* (c) 2014-2019 Evan You

View File

@@ -1,86 +1,96 @@
{
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~f0e94b19.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~f0e94b19.js?id=6990e3e93c9774adbcab",
"/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~0ee95e5e.js": "/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~0ee95e5e.js?id=2df77e8c18a95a8b547b",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js?id=3f7d471e29e47abe2fcb",
"/chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser.js?id=27dc0a5d34766399afb9",
"/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js": "/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js?id=9801ef530d68da49e60f",
"/chunks/files~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/files~chunks/shared-files~chunks/shared/file-browser.js?id=ad8eee46285f674c0ac7",
"/chunks/admin.js": "/chunks/admin.js?id=7dfbff25a4e785058266",
"/chunks/dashboard~chunks/dashboard-oasis.js": "/chunks/dashboard~chunks/dashboard-oasis.js?id=249d4e967b53a594128e",
"/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=934fc255a8e604d5d152",
"/chunks/profile~chunks/settings-password.js": "/chunks/profile~chunks/settings-password.js?id=625d71185e00638d4502",
"/vendors~chunks/platform~chunks/shared.js": "/vendors~chunks/platform~chunks/shared.js?id=0a546ed495f1f5583815",
"/js/main.js": "/js/main.js?id=af6d30cdaaf47b6831eb",
"/css/app.css": "/css/app.css?id=f3686ab1dab91901dada",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=94b0c4dad940de31fcf9",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=58baefeb9cb14a9638de",
"/chunks/app-billings.js": "/chunks/app-billings.js?id=56fa0e764a7e34d33e26",
"/chunks/app-email.js": "/chunks/app-email.js?id=cd9d6ed9e9d015da9d91",
"/chunks/app-index.js": "/chunks/app-index.js?id=cb3498e406901deb0930",
"/chunks/app-language.js": "/chunks/app-language.js?id=beb4fd36fad32b89ca64",
"/chunks/app-others.js": "/chunks/app-others.js?id=034793903665db47a0bc",
"/chunks/app-payments.js": "/chunks/app-payments.js?id=f034a7f9f588fd0665f5",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=1edbf740ed8cbdf76349",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=201081c3c347b4e0eeed",
"/chunks/billings-detail.js": "/chunks/billings-detail.js?id=00c8fe17dc6761969871",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=722d31adc228f19dc49b",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=f67f77d78c62e27feb8d",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=16ec4c26914130f29cf3",
"/chunks/dashboard-oasis.js": "/chunks/dashboard-oasis.js?id=afa481d47d0bd3ba3750",
"/chunks/database.js": "/chunks/database.js?id=acb65d4499d57791e69f",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=7253c7e2c02288667f10",
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=b2bd555b09d473dcc1fd",
"/chunks/files.js": "/chunks/files.js?id=b38b95a7e3858280da4d",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=87fa0dea6e278f0d9fa6",
"/chunks/homepage.js": "/chunks/homepage.js?id=ca2707643c4b9dd27c07",
"/chunks/installation-disclaimer.js": "/chunks/installation-disclaimer.js?id=9ca651dff7a3710ce93d",
"/chunks/invoices.js": "/chunks/invoices.js?id=f9aa473594e93de9252a",
"/chunks/not-found-shared.js": "/chunks/not-found-shared.js?id=fe4997955d98dc130e24",
"/chunks/oasis/homepage.js": "/chunks/oasis/homepage.js?id=016fb5b10d2cdfd629fa",
"/chunks/oasis/platba.js": "/chunks/oasis/platba.js?id=dca258b55be61f309e5a",
"/chunks/oasis/sign-up.js": "/chunks/oasis/sign-up.js?id=f6db6503b0ede98407e9",
"/chunks/oasis/upgrade-billing.js": "/chunks/oasis/upgrade-billing.js?id=75925dc386035a7761b3",
"/chunks/oasis/upgrade-plan.js": "/chunks/oasis/upgrade-plan.js?id=cd4d7e87fa906a6dbb5c",
"/chunks/oasis/user-create.js": "/chunks/oasis/user-create.js?id=6ef36c88a16c3301ba26",
"/chunks/oasis/users.js": "/chunks/oasis/users.js?id=72eb059878163fa82b6b",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=dba2b029788bdcc0d6be",
"/chunks/pages.js": "/chunks/pages.js?id=a2783fc555f54053c444",
"/chunks/plan.js": "/chunks/plan.js?id=14b68b27e7b3cf402292",
"/chunks/plan-create.js": "/chunks/plan-create.js?id=2af6a691a7e9563f8182",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=b3c047d76d2e728fb57a",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=d1031a16043e049d44a0",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=d5dc3e2cbea7c7bfed78",
"/chunks/plans.js": "/chunks/plans.js?id=732556499c15e7b5b748",
"/chunks/platform.js": "/chunks/platform.js?id=4e73136ec69dabfa4e3e",
"/chunks/profile.js": "/chunks/profile.js?id=e6f4430fee84eb81c4cd",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=20059be7a7ee9235b0b5",
"/chunks/settings.js": "/chunks/settings.js?id=1ea4980db859d9a8ceac",
"/chunks/settings-create-payment-methods.js": "/chunks/settings-create-payment-methods.js?id=e387c2e068942cceab70",
"/chunks/settings-invoices.js": "/chunks/settings-invoices.js?id=32a3a5fb8a3bdf03939f",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=add07c5831e191665fd8",
"/chunks/settings-payment-methods.js": "/chunks/settings-payment-methods.js?id=784d67c404e3c718d036",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=d7f8dbc8cc0102b66d95",
"/chunks/settings-subscription.js": "/chunks/settings-subscription.js?id=feb0467a0e9308a76cd8",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=a9a5e2bcaadb0018dc1c",
"/chunks/shared.js": "/chunks/shared.js?id=1724cf1960fa46605038",
"/chunks/shared-files.js": "/chunks/shared-files.js?id=301fa2f06ccd325e516d",
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=00ade8715b4afcc3facb",
"/chunks/shared/file-browser.js": "/chunks/shared/file-browser.js?id=a5e24aab9368f14b970a",
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=4e3b338733b110152237",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=a1dc638dc0d58831e90e",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=640ab6090a0fe82ee41b",
"/chunks/stripe-credentials.js": "/chunks/stripe-credentials.js?id=7be9e7a6ec17078f1fe3",
"/chunks/subscription-plans.js": "/chunks/subscription-plans.js?id=920db117716755fac6d6",
"/chunks/subscription-service.js": "/chunks/subscription-service.js?id=9b79852afd388cd63f69",
"/chunks/upgrade-billing.js": "/chunks/upgrade-billing.js?id=835e4414315d863e6d48",
"/chunks/upgrade-plan.js": "/chunks/upgrade-plan.js?id=c2072dae002b8d96e73b",
"/chunks/user.js": "/chunks/user.js?id=86c4078758426c028534",
"/chunks/user-create.js": "/chunks/user-create.js?id=973f01693148d88e0e17",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=c5adc2c83a00311b9a6f",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=6e354dcc0e4814ee904a",
"/chunks/user-invoices.js": "/chunks/user-invoices.js?id=6cf2f0d87c686b3705ae",
"/chunks/user-password.js": "/chunks/user-password.js?id=eef7fb46024df6b733d8",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=b5a2c493e8bc83acc416",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=8a734cfb59de202c3a54",
"/chunks/users.js": "/chunks/users.js?id=e5f8048754c336bd9d5e"
"/js/main.js": "/js/main.js",
"/css/app.css": "/css/app.css",
"/chunks/admin.js": "/chunks/admin.js?id=2971d15f4e0bd0662482",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=3036df3e72596fabc42e",
"/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js": "/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js?id=62b552a0492fe95b2223",
"/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~cf616679.js": "/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~cf616679.js?id=fd241499c4e3b6a88840",
"/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~eeab5771.js": "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~eeab5771.js?id=dc1abd740ef0db3451a2",
"/chunks/admin~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/admin~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser.js?id=a76042074e958eaab108",
"/chunks/admin~chunks/files~chunks/settings~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/admin~chunks/files~chunks/settings~chunks/shared-files~chunks/shared/file-browser.js?id=9b66c2dab4c6103bb53c",
"/chunks/admin~chunks/platform.js": "/chunks/admin~chunks/platform.js?id=7b37d12eb7ff79e1eb53",
"/chunks/admin~chunks/platform~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/shared.js?id=7e94943976a0aea65e09",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=b4e2d99a172f06a1d312",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~605f4c49.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~605f4c49.js?id=1ae1e65bb6a5ed7c3e10",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js?id=7702f37f277478ad66c6",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~b9e5655a.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~b9e5655a.js?id=04f0cd9719723459b685",
"/chunks/app-billings.js": "/chunks/app-billings.js?id=82133cc16f55222bbbe6",
"/chunks/app-email.js": "/chunks/app-email.js?id=c578a85112c6a4b1ed0e",
"/chunks/app-index.js": "/chunks/app-index.js?id=5bf1c4a8df85876205a0",
"/chunks/app-language.js": "/chunks/app-language.js?id=ccf2292ad048d4bfad60",
"/chunks/app-language~chunks/app-settings~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pag~824d674f.js": "/chunks/app-language~chunks/app-settings~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pag~824d674f.js?id=46d89e7310e4babf1999",
"/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js": "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js?id=da04bade02d8f48d5f8b",
"/chunks/app-others.js": "/chunks/app-others.js?id=9156adba3b1697a8bf3e",
"/chunks/app-payments.js": "/chunks/app-payments.js?id=7e1a982c90174f568fb2",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=acc6ba7a93681f0d5d64",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=d0e3e046e147ca928f34",
"/chunks/billings-detail.js": "/chunks/billings-detail.js?id=d0ade32264f71dd7a2af",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=f5276b101b2e0c97d6d1",
"/chunks/contact-us~chunks/dynamic-page~chunks/homepage.js": "/chunks/contact-us~chunks/dynamic-page~chunks/homepage.js?id=22bd5db44c72e8de5f5b",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=48dc53ccbd502c2739ec",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=9825336101be68307708",
"/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/plans~chunks/settings-i~0e2a0654.js": "/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/plans~chunks/settings-i~0e2a0654.js?id=9c449e322b1d52b8ad89",
"/chunks/database.js": "/chunks/database.js?id=7374830dc3cbddf41abb",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=6dccc2158cc6278f683d",
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=208de84df68177288a2a",
"/chunks/files.js": "/chunks/files.js?id=ee5b19530d832c6f9f34",
"/chunks/files~chunks/platform~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/files~chunks/platform~chunks/shared-files~chunks/shared/file-browser.js?id=39233d603662ca3738e8",
"/chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser.js?id=4231d578d933b87cf7a2",
"/chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~chunks/sha~8510f6c9.js": "/chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~chunks/sha~8510f6c9.js?id=b4ccb4a816e5c72a0b85",
"/chunks/files~chunks/settings-subscription~chunks/shared-files~chunks/shared/file-browser~chunks/user~9058a49f.js": "/chunks/files~chunks/settings-subscription~chunks/shared-files~chunks/shared/file-browser~chunks/user~9058a49f.js?id=31a17ad1d2536342abbe",
"/chunks/files~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/files~chunks/shared-files~chunks/shared/file-browser.js?id=5159a98127718c5fc768",
"/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js": "/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js?id=628ee9736f507e6213b4",
"/chunks/files~chunks/shared/file-browser.js": "/chunks/files~chunks/shared/file-browser.js?id=44899a3c3880630dbcd9",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=877a9289b77ac3885042",
"/chunks/homepage.js": "/chunks/homepage.js?id=48e0e9b3c870c46218ce",
"/chunks/installation-disclaimer.js": "/chunks/installation-disclaimer.js?id=c523e816ae410f52d767",
"/chunks/invoices.js": "/chunks/invoices.js?id=432dbcaa4cff9f76d093",
"/chunks/not-found.js": "/chunks/not-found.js?id=7204a74c2db0ab70149c",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=4c04e9f1bbecd8d1d9ba",
"/chunks/pages.js": "/chunks/pages.js?id=99b0fdc98f5a75997fa0",
"/chunks/plan.js": "/chunks/plan.js?id=ac3046761e9083aa3053",
"/chunks/plan-create.js": "/chunks/plan-create.js?id=b966184a7aa84bdd297e",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=f193816778245ea66d02",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=66123f72696b47a986a2",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=08e2056bc3744b2ea8f9",
"/chunks/plans.js": "/chunks/plans.js?id=83fc2cc3cd4b76c8f8f0",
"/chunks/platform.js": "/chunks/platform.js?id=2abcf9db97eafddc7dfb",
"/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=7e8eacb61e51486a09d9",
"/chunks/profile.js": "/chunks/profile.js?id=1c1c666004fb44b1c404",
"/chunks/profile~chunks/settings-password.js": "/chunks/profile~chunks/settings-password.js?id=d0a44ee2cc3e9882c14a",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=e00ee12cde704060e15b",
"/chunks/settings.js": "/chunks/settings.js?id=fcc97a29894164e2977c",
"/chunks/settings-create-payment-methods.js": "/chunks/settings-create-payment-methods.js?id=88849e6ddce9226d49a5",
"/chunks/settings-invoices.js": "/chunks/settings-invoices.js?id=444b9bbc310647ddd297",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=46961d5c0fc91f4ad638",
"/chunks/settings-payment-methods.js": "/chunks/settings-payment-methods.js?id=3bc709a228c0849a6f62",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=0c243c68b17ca976d05a",
"/chunks/settings-subscription.js": "/chunks/settings-subscription.js?id=22e5c49d5b0a154e1a28",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=c6b88005b133268ed88f",
"/chunks/shared.js": "/chunks/shared.js?id=a2c4342bfddd4946cb85",
"/chunks/shared-files.js": "/chunks/shared-files.js?id=8d6ff3bdf8b295fde3d0",
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=3d5c7754d438830a4204",
"/chunks/shared/file-browser.js": "/chunks/shared/file-browser.js?id=f46e9dc63c1313bc2256",
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=e8aedb75df7fe227d693",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=162161aa204ab6931826",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=ce15b1156cf37c0a9703",
"/chunks/stripe-credentials.js": "/chunks/stripe-credentials.js?id=1acdec3a157c8943a88d",
"/chunks/subscription-plans.js": "/chunks/subscription-plans.js?id=a843f8cf90ff1e3168e8",
"/chunks/subscription-service.js": "/chunks/subscription-service.js?id=90c1aa9431689a89eb3d",
"/chunks/upgrade-billing.js": "/chunks/upgrade-billing.js?id=b06efc03a40bcba2bdad",
"/chunks/upgrade-billing~chunks/upgrade-plan.js": "/chunks/upgrade-billing~chunks/upgrade-plan.js?id=0bdf2950a5a73e6e6975",
"/chunks/upgrade-plan.js": "/chunks/upgrade-plan.js?id=35179531a8241da128e9",
"/chunks/user.js": "/chunks/user.js?id=3090bfd5b85dd1b200ec",
"/chunks/user-create.js": "/chunks/user-create.js?id=e1e6127d661c7edf0793",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=8dfec8efd3019616377b",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=b9b70e43cf551a574443",
"/chunks/user-invoices.js": "/chunks/user-invoices.js?id=6c4d0e9e058be11dc1f7",
"/chunks/user-password.js": "/chunks/user-password.js?id=a4b4ab4f4af11533eb4d",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=4aec2d7b60ec0bc35fb9",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=99efdd410910267db66e",
"/chunks/users.js": "/chunks/users.js?id=d28a9ac62a41f1ca4af8",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~2fac28cc.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~2fac28cc.js?id=57c854adb91ed9a9d088",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~d5e36d91.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~d5e36d91.js?id=170765b4fd923b62195c",
"/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3",
"/vendors~chunks/platform~chunks/shared.js": "/vendors~chunks/platform~chunks/shared.js?id=eb141834bc24b72d8e92"
}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,30 @@
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <http://feross.org>
* @license MIT
*/
/*! Copyright Twitter Inc. and other contributors. Licensed under MIT */
/**
* @licstart The following is the entire license notice for the
* Javascript code in this page
*
* Copyright 2020 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @licend The above is the entire license notice for the
* Javascript code in this page
*/

View File

@@ -5,13 +5,14 @@
<Alert />
<ToastrWrapper />
<CookieDisclaimer />
<Vignette />
<!--Show spinner before translations is loaded-->
<Spinner v-if="! isLoadedTranslations"/>
<Spinner v-if="! isLoaded"/>
<!--App view-->
<router-view v-if="isLoadedTranslations" />
<router-view v-if="isLoaded" />
<Vignette />
</div>
</template>
@@ -34,7 +35,7 @@ export default {
},
data() {
return {
isLoadedTranslations: false
isLoaded: false
}
},
methods: {
@@ -44,25 +45,12 @@ export default {
},
beforeMount() {
// Get language translations
this.$store.dispatch('getLanguageTranslations', this.$root.$data.config.language)
.then(() => {
this.isLoadedTranslations = true
// Store config to vuex
this.$store.commit('INIT', {
config: this.$root.$data.config,
rootDirectory: {
name: this.$t('locations.home'),
location: 'base',
id: undefined
}
})
})
// Get installation state
let installation = this.$root.$data.config.installation
if (['setup-disclaimer', 'setup-database'].includes(installation))
this.isLoaded = true
// Redirect to database verify code
if (installation === 'setup-database')
this.$router.push({name: 'PurchaseCode'})
@@ -70,6 +58,22 @@ export default {
// Redirect to starting installation process
if (installation === 'setup-disclaimer')
this.$router.push({name: 'InstallationDisclaimer'})
if (installation === 'setup-done')
this.$store.dispatch('getLanguageTranslations', this.$root.$data.config.language)
.then(() => {
this.isLoaded = true
// Store config to vuex
this.$store.commit('INIT', {
config: this.$root.$data.config,
rootDirectory: {
name: this.$t('locations.home'),
location: 'base',
id: undefined
}
})
})
},
mounted() {
this.$checkOS()

View File

@@ -0,0 +1,51 @@
<template>
<div v-if="isVisible" class="popover-item">
<slot></slot>
</div>
</template>
<script>
import {events} from '@/bus'
export default {
name: 'PopoverItem',
props: [
'name'
],
data() {
return {
isVisible: false,
}
},
mounted() {
events.$on('popover:open', name => {
if (this.name === name) this.isVisible = !this.isVisible
})
events.$on('unClick', () => this.isVisible = false)
}
}
</script>
<style scoped lang="scss">
@import "@assets/vuefilemanager/_variables";
@import "@assets/vuefilemanager/_mixins";
.popover-item {
min-width: 250px;
position: absolute;
z-index: 9;
box-shadow: $shadow;
background: white;
border-radius: 8px;
overflow: hidden;
right: 0;
top: 50px;
}
@media (prefers-color-scheme: dark) {
.popover-item {
background: $dark_mode_foreground;
}
}
</style>

View File

@@ -0,0 +1,18 @@
<template>
<div class="popover-wrapper">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'PopoverWrapper',
}
</script>
<style scoped lang="scss">
.popover-wrapper {
position: relative;
}
</style>

View File

@@ -0,0 +1,28 @@
<template>
<div class="toolbar-button-wrapper">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'ToolbarWrapper',
}
</script>
<style scoped lang="scss">
.toolbar-button-wrapper {
margin-left: 28px;
display: flex;
align-items: center;
}
@media only screen and (max-width: 1024px) {
.toolbar-button-wrapper {
margin-left: 25px;
}
}
</style>

View File

@@ -0,0 +1,21 @@
<template>
<div class="toolbar-tools">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'ToolbarWrapper',
}
</script>
<style scoped lang="scss">
@import "@assets/vuefilemanager/_variables";
@import "@assets/vuefilemanager/_mixins";
.toolbar-tools {
text-align: right;
display: flex;;
}
</style>

View File

@@ -193,21 +193,21 @@ export default {
Option
},
computed: {
...mapGetters(['user', 'fileInfoDetail']),
...mapGetters(['user', 'clipboard']),
hasFolder() {
return this.fileInfoDetail.find(item => item.type === 'folder')
return this.clipboard.find(item => item.type === 'folder')
},
hasFile() {
return this.fileInfoDetail.find(item => item.type !== 'folder')
return this.clipboard.find(item => item.type !== 'folder')
},
isMultiSelectContextMenu() {
// If is context Menu open on multi selected items open just options for the multi selected items
if (this.fileInfoDetail.length > 1 && this.fileInfoDetail.includes(this.item))
if (this.clipboard.length > 1 && this.clipboard.includes(this.item))
return false
// If is context Menu open for the non selected item open options for the single item
if (this.fileInfoDetail.length < 2 || !this.fileInfoDetail.includes(this.item))
if (this.clipboard.length < 2 || !this.clipboard.includes(this.item))
return true
},
favourites() {
@@ -250,11 +250,11 @@ export default {
restoreItem() {
// If is item not in selected items restore just this single item
if (!this.fileInfoDetail.includes(this.item))
if (!this.clipboard.includes(this.item))
this.$store.dispatch('restoreItem', this.item)
// If is item in selected items restore all items from fileInfoDetail
if (this.fileInfoDetail.includes(this.item))
// If is item in selected items restore all items from clipboard
if (this.clipboard.includes(this.item))
this.$store.dispatch('restoreItem', null)
},
shareCancel() {
@@ -267,13 +267,14 @@ export default {
events.$emit('popup:open', {name: 'move', item: [this.item]})
},
shareItem() {
if (this.item.shared) {
// Open edit share popup
events.$emit('popup:open', {name: 'share-edit', item: this.item})
} else {
// Open create share popup
events.$emit('popup:open', {name: 'share-create', item: this.item})
}
let event = this.item.shared
? 'share-edit'
: 'share-create'
events.$emit('popup:open', {
name: event,
item: this.item
})
},
addToFavourites() {
// Check if folder is in favourites and then add/remove from favourites
@@ -282,12 +283,12 @@ export default {
!this.favourites.find(el => el.id === this.item.id)
) {
// Add to favourite folder that is not selected
if (!this.fileInfoDetail.includes(this.item)) {
if (!this.clipboard.includes(this.item)) {
this.$store.dispatch('addToFavourites', this.item)
}
// Add to favourites all selected folders
if (this.fileInfoDetail.includes(this.item)) {
if (this.clipboard.includes(this.item)) {
this.$store.dispatch('addToFavourites', null)
}
} else {
@@ -295,7 +296,7 @@ export default {
}
},
downloadItem() {
if (this.fileInfoDetail.length > 1)
if (this.clipboard.length > 1)
this.$store.dispatch('downloadFiles')
else {
this.$downloadFile(this.item.file_url, this.item.name + '.' + this.item.mimetype)
@@ -303,18 +304,18 @@ export default {
},
ItemDetail() {
// Dispatch load file info detail
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
// Show panel if is not open
this.$store.dispatch('fileInfoToggle', true)
},
deleteItem() {
// If is context menu open on non selected item delete this single item
if (!this.fileInfoDetail.includes(this.item)) {
if (!this.clipboard.includes(this.item)) {
this.$store.dispatch('deleteItem', this.item)
}
// If is context menu open to multi selected items dele this selected items
if (this.fileInfoDetail.includes(this.item)) {
if (this.clipboard.includes(this.item)) {
this.$store.dispatch('deleteItem')
}
},
@@ -385,12 +386,6 @@ export default {
}
}
},
mounted() {
events.$on('actualShowingImage:ContextMenu', (item) => {
this.item = item
})
},
created() {
events.$on('showContextMenuPreview:show', (item) => {
if (!this.showFromPreview) {

View File

@@ -1,59 +0,0 @@
<template>
<div v-if="isVisible" class="sorting-preview">
<SortingAndPreviewMenu />
</div>
</template>
<script>
import SortingAndPreviewMenu from '@/components/FilesView/SortingAndPreviewMenu'
import { events } from '@/bus'
export default {
name: 'DesktopSortingAndPreview',
components: {SortingAndPreviewMenu},
data () {
return {
isVisible: false
}
},
mounted () {
events.$on('sortingAndPreview', (state) => {
this.isVisible = state
})
events.$on('unClick', () => {
this.isVisible = false
})
}
}
</script>
<style scoped lang="scss">
@import "@assets/vuefilemanager/_variables";
@import "@assets/vuefilemanager/_mixins";
.sorting-preview {
min-width: 250px;
position: absolute;
z-index: 99;
box-shadow: $shadow;
background: white;
border-radius: 8px;
overflow: hidden;
right: 66px;
top: 63px;
&.showed {
display: block;
}
}
@media (prefers-color-scheme: dark) {
.sorting-preview {
background: $dark_mode_foreground;
}
}
</style>

View File

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

View File

@@ -1,20 +1,30 @@
<template>
<MultiSelected :title="title" :subtitle="subtitle" id="multi-select-ui" v-show="isVisible"/>
<TitlePreview
icon="check-square"
:title="title"
:subtitle="subtitle"
id="drag-ui"
v-show="isVisible"
/>
</template>
<script>
import MultiSelected from '@/components/FilesView/MultiSelected'
import TitlePreview from '@/components/FilesView/TitlePreview'
import { mapGetters } from 'vuex'
import { events } from '@/bus'
export default {
name: 'DragUI',
components: { MultiSelected },
components: {
TitlePreview
},
computed: {
...mapGetters(['fileInfoDetail']),
...mapGetters([
'clipboard'
]),
title() {
let filesLength = this.fileInfoDetail.length,
hasDraggedItem = this.fileInfoDetail.includes(this.draggedItem)
let filesLength = this.clipboard.length,
hasDraggedItem = this.clipboard.includes(this.draggedItem)
// Title for multiple selected items
if (filesLength > 1 && hasDraggedItem) {
@@ -27,8 +37,8 @@ export default {
}
},
subtitle() {
let filesLength = this.fileInfoDetail.length,
hasDraggedItem = this.fileInfoDetail.includes(this.draggedItem)
let filesLength = this.clipboard.length,
hasDraggedItem = this.clipboard.includes(this.draggedItem)
// Subtitle for multiple selected items
if (filesLength > 1 && hasDraggedItem) {
@@ -56,7 +66,6 @@ export default {
}
},
created() {
// Handle Drag & Drop Ghost show
events.$on('dragstart', data => {
this.draggedItem = data
@@ -65,9 +74,7 @@ export default {
}, 100)
})
events.$on('drop', () => {
this.isVisible = false
})
events.$on('drop', () => this.isVisible = false)
}
}
</script>
@@ -76,7 +83,7 @@ export default {
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
#multi-select-ui {
#drag-ui {
max-width: 300px;
min-width: 250px;
position: fixed;
@@ -89,7 +96,7 @@ export default {
}
@media (prefers-color-scheme: dark) {
#multi-select-ui {
#drag-ui {
background: $dark_mode_foreground;
}
}

View File

@@ -0,0 +1,120 @@
<template>
<div class="empty-page" v-if="isLoading || isEmpty">
<div class="empty-state">
<!--Shared empty message-->
<div class="text-content" v-if="$isThisLocation(['shared']) && ! isLoading">
<h1 class="title">{{ $t('shared.empty_shared') }}</h1>
</div>
<!--Trash empty message-->
<div class="text-content" v-if="$isThisLocation(['trash', 'trash-root']) && ! isLoading">
<h1 class="title">{{ $t('empty_page.title') }}</h1>
</div>
<!--Trash empty message-->
<div class="text-content" v-if="$isThisLocation(['participant_uploads']) && ! isLoading">
<h1 class="title">{{ $t('messages.nothing_from_participants') }}</h1>
</div>
<!--Base file browser empty message-->
<div class="text-content" v-if="$isThisLocation(['base', 'public', 'latest']) && !isLoading">
<h1 class="title">{{ $t('empty_page.title') }}</h1>
<p v-if="$checkPermission(['master', 'editor'])" class="description">{{ $t('empty_page.description') }}</p>
<ButtonUpload
v-if="$checkPermission(['master', 'editor'])"
button-style="theme"
>
{{ $t('empty_page.call_to_action') }}
</ButtonUpload>
</div>
<!--Spinner-->
<div class="text-content" v-if="isLoading">
<Spinner />
</div>
</div>
</div>
</template>
<script>
import ButtonUpload from '@/components/FilesView/ButtonUpload'
import Spinner from '@/components/FilesView/Spinner'
import {mapGetters} from 'vuex'
export default {
name: 'EmptyFilePage',
props: [
'title',
'description'
],
components: {
ButtonUpload,
Spinner,
},
computed: {
...mapGetters([
'currentFolder',
'isLoading',
'entries',
]),
isEmpty() {
return this.entries && this.entries.length == 0
}
}
}
</script>
<style scoped lang="scss">
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.empty-page {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
margin-top: 85px;
display: flex;
align-items: center;
.empty-state {
margin: 0 auto;
padding-left: 15px;
padding-right: 15px;
}
}
.text-content {
text-align: center;
margin: 30px 0;
.title {
@include font-size(20);
color: $text;
font-weight: 700;
margin: 0;
}
.description {
@include font-size(13);
color: $text-muted;
margin-bottom: 20px;
display: block;
}
}
@media (prefers-color-scheme: dark) {
.text-content {
.title {
color: $dark_mode_text_primary;
}
.description {
color: $dark_mode_text_secondary;
}
}
}
</style>

View File

@@ -1,113 +0,0 @@
<template>
<div class="empty-page" v-if="isLoading || isEmpty">
<div class="empty-state">
<!--Shared empty message-->
<div class="text-content" v-if="$isThisLocation(['shared']) && ! isLoading">
<h1 class="title">{{ $t('shared.empty_shared') }}</h1>
</div>
<!--Trash empty message-->
<div class="text-content" v-if="$isThisLocation(['trash', 'trash-root']) && ! isLoading">
<h1 class="title">{{ $t('empty_page.title') }}</h1>
</div>
<!--Trash empty message-->
<div class="text-content" v-if="$isThisLocation(['participant_uploads']) && ! isLoading">
<h1 class="title">{{ $t('messages.nothing_from_participants') }}</h1>
</div>
<!--Base file browser empty message-->
<div class="text-content" v-if="$isThisLocation(['base', 'public', 'latest']) && !isLoading">
<h1 class="title">{{ $t('empty_page.title') }}</h1>
<p v-if="$checkPermission(['master', 'editor'])" class="description">{{ $t('empty_page.description') }}</p>
<ButtonUpload
v-if="$checkPermission(['master', 'editor'])"
button-style="theme"
>
{{ $t('empty_page.call_to_action') }}
</ButtonUpload>
</div>
<!--Spinner-->
<div class="text-content" v-if="isLoading">
<Spinner/>
</div>
</div>
</div>
</template>
<script>
import ButtonUpload from '@/components/FilesView/ButtonUpload'
import Spinner from '@/components/FilesView/Spinner'
import {mapGetters} from 'vuex'
export default {
name: 'EmptyPage',
props: ['title', 'description'],
components: {
ButtonUpload,
Spinner
},
computed: {
...mapGetters(['data', 'isLoading', 'currentFolder']),
isEmpty() {
return this.data && this.data.length == 0
}
}
}
</script>
<style scoped lang="scss">
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.empty-page {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
margin-top: 85px;
display: flex;
align-items: center;
.empty-state {
margin: 0 auto;
padding-left: 15px;
padding-right: 15px;
}
}
.text-content {
text-align: center;
margin: 30px 0;
.title {
@include font-size(20);
color: $text;
font-weight: 700;
margin: 0;
}
.description {
@include font-size(13);
color: $text-muted;
margin-bottom: 20px;
display: block;
}
}
@media (prefers-color-scheme: dark) {
.text-content {
.title {
color: $dark_mode_text_primary;
}
.description {
color: $dark_mode_text_secondary;
}
}
}
</style>

View File

@@ -0,0 +1,236 @@
<template>
<div id="mobile-actions-wrapper">
<!--Base location-->
<div v-if="$isThisLocation(['base']) && $checkPermission(['master', 'editor']) && ! isSelectMode" class="mobile-actions">
<MobileActionButton @click.native="showLocations" icon="filter">
{{ filterLocationTitle }}
</MobileActionButton>
<MobileActionButton @click.native="createFolder" icon="folder-plus">
{{ $t('context_menu.add_folder') }}
</MobileActionButton>
<MobileActionButtonUpload>
{{ $t('context_menu.upload') }}
</MobileActionButtonUpload>
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
{{ $t('context_menu.select') }}
</MobileActionButton>
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
{{ $t('preview_sorting.preview_sorting_button') }}
</MobileActionButton>
</div>
<!--Base location editor-->
<div v-if="$isThisLocation('public') && $checkPermission('editor') && ! isSelectMode" class="mobile-actions">
<MobileActionButton @click.native="createFolder" icon="folder-plus">
{{ $t('context_menu.add_folder') }}
</MobileActionButton>
<MobileActionButtonUpload>
{{ $t('context_menu.upload') }}
</MobileActionButtonUpload>
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
{{ $t('context_menu.select') }}
</MobileActionButton>
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
{{ $t('preview_sorting.preview_sorting_button') }}
</MobileActionButton>
</div>
<!--Base location visitor-->
<div v-if="$isThisLocation('public') && $checkPermission('visitor') && ! isSelectMode" class="mobile-actions">
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
{{ $t('context_menu.select') }}
</MobileActionButton>
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
{{ $t('preview_sorting.preview_sorting_button') }}
</MobileActionButton>
</div>
<!--Recent uploads location-->
<div v-if="$isThisLocation('latest') && ! isSelectMode" class="mobile-actions">
<MobileActionButton @click.native="showLocations" icon="filter">
{{ filterLocationTitle }}
</MobileActionButton>
<MobileActionButtonUpload>
{{ $t('context_menu.upload') }}
</MobileActionButtonUpload>
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
{{ $t('context_menu.select') }}
</MobileActionButton>
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
{{ $t('preview_sorting.preview_sorting_button') }}
</MobileActionButton>
</div>
<!--Trash location--->
<div v-if="$isThisLocation(['trash', 'trash-root']) && ! isSelectMode" class="mobile-actions">
<MobileActionButton @click.native="showLocations" icon="filter">
{{ filterLocationTitle }}
</MobileActionButton>
<MobileActionButton @click.native="$store.dispatch('emptyTrash')" icon="trash">
{{ $t('context_menu.empty_trash') }}
</MobileActionButton>
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
{{ $t('context_menu.select') }}
</MobileActionButton>
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
{{ $t('preview_sorting.preview_sorting_button') }}
</MobileActionButton>
</div>
<!--Shared location--->
<div v-if="$isThisLocation(['shared', 'participant_uploads']) && ! isSelectMode" class="mobile-actions">
<MobileActionButton @click.native="showLocations" icon="filter">
{{ filterLocationTitle }}
</MobileActionButton>
<MobileActionButton @click.native="enableMultiSelectMode" icon="check-square">
{{ $t('context_menu.select') }}
</MobileActionButton>
<MobileActionButton @click.native="showViewOptions" icon="preview-sorting">
{{ $t('preview_sorting.preview_sorting_button') }}
</MobileActionButton>
</div>
<!-- Multi select mode -->
<div v-if="isSelectMode" class="mobile-actions">
<MobileActionButton @click.native="selectAll" icon="check-square">
{{ $t('mobile_selecting.select_all') }}
</MobileActionButton>
<MobileActionButton @click.native="deselectAll" icon="x-square">
{{ $t('mobile_selecting.deselect_all') }}
</MobileActionButton>
<MobileActionButton @click.native="disableMultiSelectMode" icon="check">
{{ $t('mobile_selecting.done') }}
</MobileActionButton>
</div>
<!--Upload Progressbar-->
<UploadProgress />
</div>
</template>
<script>
import MobileActionButtonUpload from '@/components/FilesView/MobileActionButtonUpload'
import MobileActionButton from '@/components/FilesView/MobileActionButton'
import UploadProgress from '@/components/FilesView/UploadProgress'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
import store from "../../store";
export default {
name: 'FileActionsMobile',
components: {
MobileActionButtonUpload,
MobileActionButton,
UploadProgress,
},
computed: {
...mapGetters([
'FilePreviewType'
]),
previewIcon() {
return this.FilePreviewType === 'list'
? 'th'
: 'th-list'
},
filterLocationTitle() {
return {
'base': 'Files',
'public': 'Files',
'shared': 'Shared',
'latest': 'Latest',
'trash': 'Trash',
'trash-root': 'Trash',
'participant_uploads': 'Participants',
}[this.$store.getters.currentFolder.location]
}
},
data() {
return {
isSelectMode: false,
}
},
methods: {
showLocations() {
events.$emit('mobile-menu:show', 'file-filter')
},
selectAll() {
this.$store.commit('ADD_ALL_ITEMS_TO_CLIPBOARD')
},
deselectAll() {
this.$store.commit('CLIPBOARD_CLEAR')
},
enableMultiSelectMode() {
this.isSelectMode = true
events.$emit('mobileSelecting:start')
},
disableMultiSelectMode() {
this.isSelectMode = false
events.$emit('mobileSelecting:stop')
},
showViewOptions() {
events.$emit('mobile-menu:show', 'file-sorting')
},
createFolder() {
events.$emit('popup:open', {name: 'create-folder'})
},
},
mounted() {
events.$on('mobileSelecting:stop', () => this.isSelectMode = false)
}
}
</script>
<style scoped lang="scss">
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.button-enter-active,
.button-leave-active {
transition: all 250ms;
}
.button-enter {
opacity: 0;
transform: translateY(-50%);
}
.button-leave-to {
opacity: 0;
transform: translateY(50%);
}
.button-leave-active {
position: absolute;
}
#mobile-actions-wrapper {
display: none;
background: white;
position: sticky;
top: 35px;
z-index: 3;
}
.mobile-actions {
white-space: nowrap;
overflow-x: auto;
margin: 0 -15px;
padding: 10px 0 10px 15px;
}
@media only screen and (max-width: 960px) {
#mobile-actions-wrapper {
display: block;
}
}
@media (prefers-color-scheme: dark) {
#mobile-actions-wrapper {
background: $dark_mode_background;
}
}
</style>

View File

@@ -1,442 +1,439 @@
<template>
<div class="file-content" id="file-content-id" :class="{ 'is-offset': filesInQueueTotal > 0, 'is-dragging': isDragging }"
@dragover.prevent
@drop.stop.prevent="dropUpload($event)"
@dragover="dragEnter"
@dragleave="dragLeave"
@keydown.delete="deleteItems"
tabindex="-1"
>
<div
:class="{'is-offset': filesInQueueTotal > 0, 'is-dragging': isDragging }"
class="file-content"
id="file-content-id"
@drop.stop.prevent="dropUpload($event)"
@keydown.delete="deleteItems"
@dragover="dragEnter"
@dragleave="dragLeave"
@dragover.prevent
tabindex="-1"
>
<div
class="files-container"
ref="fileContainer"
:class="{'is-fileinfo-visible': fileInfoVisible && !$isMinimalScale() , 'mobile-multi-select' : mobileMultiSelect}"
@click.self="filesContainerClick"
>
<!--MobileToolbar-->
:class="{'is-visible': isVisibleSidebar, 'mobile-multi-select': isMultiSelect}"
@click.self="filesContainerClick"
class="files-container"
ref="fileContainer"
>
<MobileToolbar />
<!--Searchbar-->
<SearchBar class="mobile-search" />
<SearchBar v-model="query" @reset-query="query = ''" class="mobile-search" :placeholder="$t('inputs.placeholder_search_files')" />
<!--Mobile Actions-->
<MobileActions />
<!--Mobile Actions-->
<FileActionsMobile />
<!--Item previews list-->
<!--Item previews list-->
<div v-if="isList" class="file-list-wrapper">
<transition-group
name="file"
tag="section"
class="file-list"
:class="FilePreviewType"
>
name="file"
tag="section"
class="file-list"
:class="FilePreviewType"
>
<FileItemList
@dragstart="dragStart(item)"
@drop.stop.native.prevent="dragFinish(item, $event)"
@contextmenu.native.prevent="contextMenu($event, item)"
:item="item"
v-for="item in data"
:key="item.id"
class="file-item"
:class="draggedItems.includes(item) ? 'dragged' : '' "
/>
@dragstart="dragStart(item)"
@drop.stop.native.prevent="dragFinish(item, $event)"
@contextmenu.native.prevent="contextMenu($event, item)"
:item="item"
v-for="item in entries"
:key="item.id"
class="file-item"
:class="draggedItems.includes(item) ? 'dragged' : '' "
/>
</transition-group>
</div>
<!--Item previews grid-->
<!--Item previews grid-->
<div v-if="isGrid" class="file-grid-wrapper">
<transition-group
name="file"
tag="section"
class="file-list"
:class="FilePreviewType"
>
name="file"
tag="section"
class="file-list"
:class="FilePreviewType"
>
<FileItemGrid
@dragstart="dragStart(item)"
@drop.native.prevent="dragFinish(item, $event)"
@contextmenu.native.prevent="contextMenu($event, item)"
:item="item"
v-for="item in data"
:key="item.id"
class="file-item"
:class="draggedItems.includes(item) ? 'dragged' : '' "
/>
@dragstart="dragStart(item)"
@drop.native.prevent="dragFinish(item, $event)"
@contextmenu.native.prevent="contextMenu($event, item)"
:item="item"
v-for="item in entries"
:key="item.id"
class="file-item"
:class="draggedItems.includes(item) ? 'dragged' : '' "
/>
</transition-group>
</div>
<!--Show empty page if folder is empty-->
<EmptyPage v-if="! isSearching" />
<!--Show empty page if folder is empty-->
<EmptyFilePage v-if="! isSearching" />
<!--Show empty page if no search results-->
<!--Show empty page if no search results-->
<EmptyMessage
v-if="isSearching && isEmpty"
:message="$t('messages.nothing_was_found')"
icon="eye-slash"
/>
v-if="isSearching && isEmpty"
:message="$t('messages.nothing_was_found')"
icon="eye-slash"
/>
</div>
<!--File Info Panel-->
<div v-if="! $isMinimalScale()" class="file-info-container" :class="{ 'is-fileinfo-visible': fileInfoVisible }">
<!--File info panel-->
<FileInfoPanel v-if="fileInfoDetail.length === 1" />
<MultiSelected v-if="fileInfoDetail.length > 1"
:title="$t('file_detail.selected_multiple')"
:subtitle="this.fileInfoDetail.length + ' ' + $tc('file_detail.items', this.fileInfoDetail.length)"
/>
<!--If file info panel empty show message-->
<EmptyMessage v-if="fileInfoDetail.length === 0" :message="$t('messages.nothing_to_preview')" icon="eye-off" />
<!--File Info Panel-->
<div :class="{'is-visible': isVisibleSidebar }" class="file-info-container">
<InfoSidebar />
</div>
</div>
</template>
<script>
import MobileToolbar from '@/components/FilesView/MobileToolbar'
import MobileActions from '@/components/FilesView/MobileActions'
import MultiSelected from '@/components/FilesView/MultiSelected'
import FileInfoPanel from '@/components/FilesView/FileInfoPanel'
import FileItemList from '@/components/FilesView/FileItemList'
import FileItemGrid from '@/components/FilesView/FileItemGrid'
import EmptyMessage from '@/components/FilesView/EmptyMessage'
import EmptyPage from '@/components/FilesView/EmptyPage'
import SearchBar from '@/components/FilesView/SearchBar'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
import FileActionsMobile from '@/components/FilesView/FileActionsMobile'
import MobileToolbar from '@/components/FilesView/MobileToolbar'
import EmptyFilePage from '@/components/FilesView/EmptyFilePage'
import EmptyMessage from '@/components/FilesView/EmptyMessage'
import FileItemList from '@/components/FilesView/FileItemList'
import FileItemGrid from '@/components/FilesView/FileItemGrid'
import InfoSidebar from '@/components/FilesView/InfoSidebar'
import SearchBar from '@/components/FilesView/SearchBar'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
import {debounce} from "lodash";
export default {
name: 'FilesContainer',
components: {
MobileToolbar,
MobileActions,
MultiSelected,
FileInfoPanel,
FileItemList,
FileItemGrid,
EmptyMessage,
SearchBar,
EmptyPage
},
computed: {
...mapGetters([
'filesInQueueTotal',
'fileInfoVisible',
'fileInfoDetail',
'currentFolder',
'FilePreviewType',
'isSearching',
'isLoading',
'data'
]),
isGrid() {
return this.FilePreviewType === 'grid'
},
isList() {
return this.FilePreviewType === 'list'
},
isEmpty() {
return this.data.length == 0
},
draggedItems() {
//Set opacity for dragged items
export default {
name: 'FilesContainer',
components: {
FileActionsMobile,
EmptyFilePage,
MobileToolbar,
FileItemList,
FileItemGrid,
EmptyMessage,
InfoSidebar,
SearchBar,
},
computed: {
...mapGetters([
'filesInQueueTotal',
'isVisibleSidebar',
'FilePreviewType',
'currentFolder',
'isSearching',
'clipboard',
'isLoading',
'entries'
]),
isGrid() {
return this.FilePreviewType === 'grid'
},
isList() {
return this.FilePreviewType === 'list'
},
isEmpty() {
return this.entries.length == 0
},
draggedItems() {
//Set opacity for dragged items
if (!this.fileInfoDetail.includes(this.draggingId)) {
return [this.draggingId]
}
if (!this.clipboard.includes(this.draggingId)) {
return [this.draggingId]
}
if (this.fileInfoDetail.includes(this.draggingId)) {
return this.fileInfoDetail
}
}
},
data() {
return {
draggingId: undefined,
isDragging: false,
mobileMultiSelect: false,
}
},
methods: {
deleteItems() {
if (this.fileInfoDetail.length > 0 && this.$checkPermission('master') || this.$checkPermission('editor')) {
this.$store.dispatch('deleteItem')
}
},
dropUpload(event) {
// Upload external file
this.$uploadExternalFiles(event, this.currentFolder.id)
if (this.clipboard.includes(this.draggingId)) {
return this.clipboard
}
}
},
watch: {
query(val) {
this.$searchFiles(val)
}
},
data() {
return {
draggingId: undefined,
isDragging: false,
isMultiSelect: false,
query: '',
}
},
methods: {
deleteItems() {
if (this.clipboard.length > 0 && this.$checkPermission('master') || this.$checkPermission('editor')) {
this.$store.dispatch('deleteItem')
}
},
dropUpload(event) {
// Upload external file
this.$uploadExternalFiles(event, this.currentFolder.id)
this.isDragging = false
},
dragEnter() {
this.isDragging = true
},
dragLeave() {
this.isDragging = false
},
dragStart(data) {
let img = document.createElement('img')
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
event.dataTransfer.setDragImage(img, 0, 0)
this.isDragging = false
},
dragEnter() {
this.isDragging = true
},
dragLeave() {
this.isDragging = false
},
dragStart(data) {
let img = document.createElement('img')
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
event.dataTransfer.setDragImage(img, 0, 0)
events.$emit('dragstart', data)
events.$emit('dragstart', data)
// Store dragged folder
this.draggingId = data
},
dragFinish(data, event) {
// Store dragged folder
this.draggingId = data
},
dragFinish(data, event) {
if (event.dataTransfer.items.length == 0) {
// Prevent to drop on file or image
if (data.type !== 'folder' || this.draggingId === data) return
if (event.dataTransfer.items.length == 0) {
// Prevent to drop on file or image
if (data.type !== 'folder' || this.draggingId === data) return
//Prevent move selected folder to folder if in beteewn selected folders
if (this.fileInfoDetail.find(item => item === data && this.fileInfoDetail.length > 1)) return
//Prevent move selected folder to folder if in beteewn selected folders
if (this.clipboard.find(item => item === data && this.clipboard.length > 1)) return
// Move folder to new parent
// Move folder to new parent
//Move item if is not included in selected items
if (!this.fileInfoDetail.includes(this.draggingId)) {
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: this.draggingId})
}
//Move item if is not included in selected items
if (!this.clipboard.includes(this.draggingId)) {
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: this.draggingId})
}
//Move selected items to folder
if (this.fileInfoDetail.length > 0 && this.fileInfoDetail.includes(this.draggingId)) {
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: null})
}
//Move selected items to folder
if (this.clipboard.length > 0 && this.clipboard.includes(this.draggingId)) {
this.$store.dispatch('moveItem', {to_item: data, noSelectedItem: null})
}
} else {
} else {
// Get id of current folder
const id = data.type !== 'folder' ? this.currentFolder.id : data.id
// Get id of current folder
const id = data.type !== 'folder' ? this.currentFolder.id : data.id
// Upload external file
this.$uploadExternalFiles(event, id)
}
// Upload external file
this.$uploadExternalFiles(event, id)
}
this.isDragging = false
},
contextMenu(event, item) {
events.$emit('contextMenu:show', event, item)
},
filesContainerClick() {
this.isDragging = false
},
contextMenu(event, item) {
events.$emit('contextMenu:show', event, item)
},
filesContainerClick() {
// Deselect items clicked by outside
this.$store.commit('CLEAR_FILEINFO_DETAIL')
}
},
created() {
events.$on('mobileSelecting:start', () => {
this.mobileMultiSelect = true
})
// Deselect items clicked by outside
this.$store.commit('CLIPBOARD_CLEAR')
}
},
created() {
events.$on('mobileSelecting:start', () => {
this.isMultiSelect = true
})
events.$on('mobileSelecting:stop', () => {
this.mobileMultiSelect = false
})
events.$on('mobileSelecting:stop', () => {
this.isMultiSelect = false
})
events.$on('drop', () => {
this.isDragging = false
events.$on('drop', () => {
this.isDragging = false
setTimeout(() => {
this.draggingId = undefined
}, 10)
})
setTimeout(() => {
this.draggingId = undefined
}, 10)
})
events.$on('fileItem:deselect', () => {
this.$store.commit('CLEAR_FILEINFO_DETAIL')
})
events.$on('fileItem:deselect', () => {
this.$store.commit('CLIPBOARD_CLEAR')
})
events.$on('scrollTop', () => {
events.$on('scrollTop', () => {
// Scroll top
var container = document.getElementsByClassName(
'files-container'
)[0]
// Scroll top
var container = document.getElementsByClassName(
'files-container'
)[0]
if (container)
container.scrollTop = 0
})
}
}
if (container)
container.scrollTop = 0
})
}
}
</script>
<style scoped lang="scss">
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
@import '@assets/vuefilemanager/_mixins';
.file-list {
.dragged {
/deep/ .is-dragenter {
border: 2px solid transparent;
}
}
}
.file-list {
.dragged {
/deep/ .is-dragenter {
border: 2px solid transparent;
}
}
}
.dragged {
opacity: 0.5;
}
.dragged {
opacity: 0.5;
}
#multi-selected {
position: fixed;
pointer-events: none;
z-index: 100;
#multi-selected {
position: fixed;
pointer-events: none;
z-index: 100;
}
}
.mobile-multi-select {
bottom: 50px !important;
top: 0px;
}
.mobile-multi-select {
bottom: 50px !important;
top: 0px;
}
.button-upload {
display: block;
text-align: center;
margin: 20px 0;
}
.button-upload {
display: block;
text-align: center;
margin: 20px 0;
}
.mobile-search {
display: none;
margin-bottom: 10px;
margin-top: 10px;
}
.mobile-search {
display: none;
margin-bottom: 10px;
margin-top: 10px;
}
.file-content {
display: flex;
.file-content {
display: flex;
&.is-dragging {
@include transform(scale(0.99));
}
}
&.is-dragging {
@include transform(scale(0.99));
}
}
.files-container {
overflow-x: hidden;
overflow-y: auto;
flex: 0 0 100%;
@include transition(150ms);
position: relative;
scroll-behavior: smooth;
.files-container {
overflow-x: hidden;
overflow-y: auto;
flex: 0 0 100%;
@include transition(150ms);
position: relative;
scroll-behavior: smooth;
&.is-fileinfo-visible {
flex: 0 1 100%;
}
&.is-visible {
flex: 0 1 100%;
}
.file-list {
.file-list {
&.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 180px);
justify-content: space-evenly;
}
}
}
&.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 180px);
justify-content: space-evenly;
}
}
}
.file-info-container {
flex: 0 0 300px;
padding-left: 20px;
overflow: auto;
}
.file-info-container {
flex: 0 0 300px;
padding-left: 20px;
overflow: auto;
}
// Transition
.file-move {
transition: transform 0.6s;
}
// Transition
.file-move {
transition: transform 0.6s;
}
.file-enter-active {
transition: all 300ms ease;
}
.file-enter-active {
transition: all 300ms ease;
}
.file-leave-active {
transition: all 0ms;
}
.file-leave-active {
transition: all 0ms;
}
.file-enter, .file-leave-to /* .list-leave-active below version 2.1.8 */
{
opacity: 0;
transform: translateX(-20px);
}
.file-enter, .file-leave-to /* .list-leave-active below version 2.1.8 */
{
opacity: 0;
transform: translateX(-20px);
}
@media only screen and (min-width: 960px) {
@media only screen and (min-width: 960px) {
.file-content {
position: absolute;
top: 72px;
left: 15px;
right: 15px;
bottom: 0;
@include transition;
overflow-y: auto;
overflow-x: hidden;
.file-content {
position: absolute;
top: 72px;
left: 15px;
right: 15px;
bottom: 0;
@include transition;
overflow-y: auto;
overflow-x: hidden;
&.is-offset {
margin-top: 50px;
}
}
}
&.is-offset {
margin-top: 50px;
}
}
}
@media only screen and (max-width: 960px) {
@media only screen and (max-width: 960px) {
.file-info-container {
display: none;
}
.file-info-container {
display: none;
}
.mobile-search {
display: block;
}
.file-content {
position: absolute;
top: 0px;
left: 15px;
right: 15px;
bottom: 0;
@include transition;
overflow-y: auto;
overflow-x: hidden;
.mobile-search {
display: block;
}
.file-content {
position: absolute;
top: 0px;
left: 15px;
right: 15px;
bottom: 0;
@include transition;
overflow-y: auto;
overflow-x: hidden;
&.is-offset {
margin-top: 50px;
}
}
}
&.is-offset {
margin-top: 50px;
}
}
}
@media only screen and (max-width: 690px) {
@media only screen and (max-width: 690px) {
.files-container {
padding-left: 15px;
padding-right: 15px;
top: 0;
left: 0;
right: 0;
bottom: 0;
position: fixed;
overflow-y: auto;
.files-container {
padding-left: 15px;
padding-right: 15px;
top: 0;
left: 0;
right: 0;
bottom: 0;
position: fixed;
overflow-y: auto;
.file-list {
.file-list {
&.grid {
grid-template-columns: repeat(auto-fill, 120px);
}
}
}
&.grid {
grid-template-columns: repeat(auto-fill, 120px);
}
}
}
.file-content {
position: absolute;
top: 0;
left: 0px;
right: 0px;
bottom: 0;
@include transition;
.file-content {
position: absolute;
top: 0;
left: 0px;
right: 0px;
bottom: 0;
@include transition;
&.is-offset {
margin-top: 50px;
}
}
&.is-offset {
margin-top: 50px;
}
}
.mobile-search {
margin-bottom: 0;
}
.mobile-search {
margin-bottom: 0;
}
.file-info-container {
display: none;
}
}
.file-info-container {
display: none;
}
}
</style>

View File

@@ -0,0 +1,63 @@
<template>
<MenuMobile name="file-filter">
<MenuMobileGroup>
<OptionGroup>
<Option @click.native="goToFiles" :title="$t('menu.files')" icon="hard-drive" :is-active="$isThisLocation('base')" is-hover-disabled="true" />
<Option @click.native="goToLatest" :title="$t('menu.latest')" icon="upload-cloud" :is-active="$isThisLocation('latest')" is-hover-disabled="true" />
<Option @click.native="goToTrash" :title="$t('menu.trash')" icon="trash" :is-active="$isThisLocation(['trash', 'trash-root'])" is-hover-disabled="true" />
</OptionGroup>
<OptionGroup>
<Option @click.native="goToShared" :title="$t('sidebar.my_shared')" icon="share" :is-active="$isThisLocation('shared')" is-hover-disabled="true" />
<Option @click.native="goToParticipantUploads" :title="$t('sidebar.participant_uploads')" icon="users" :is-active="$isThisLocation('participant_uploads')" is-hover-disabled="true" />
</OptionGroup>
</MenuMobileGroup>
</MenuMobile>
</template>
<script>
import MenuMobileGroup from '@/components/Mobile/MenuMobileGroup'
import OptionGroup from '@/components/FilesView/OptionGroup'
import MenuMobile from '@/components/Mobile/MenuMobile'
import Option from '@/components/FilesView/Option'
import {mapGetters} from 'vuex'
export default {
name: 'FileMenuMobile',
components: {
MenuMobileGroup,
OptionGroup,
MenuMobile,
Option,
},
computed: {
...mapGetters([
'homeDirectory'
]),
},
methods: {
flushBrowseHistory() {
this.$store.commit('FLUSH_FOLDER_HISTORY')
},
goToFiles() {
this.$store.dispatch('getFolder', [{folder: this.homeDirectory, back: false, init: true}])
this.flushBrowseHistory()
},
goToLatest() {
this.$store.dispatch('getLatest')
this.flushBrowseHistory()
},
goToTrash() {
this.$store.dispatch('getTrash')
this.flushBrowseHistory()
},
goToShared() {
this.$store.dispatch('getShared', [{back: false, init: false}])
this.flushBrowseHistory()
},
goToParticipantUploads() {
this.$store.dispatch('getParticipantUploads')
this.flushBrowseHistory()
}
}
}
</script>

View File

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

View File

@@ -1,218 +0,0 @@
<template>
<div class="file-info-content" v-if="fileInfoDetail.length === 1">
<div class="file-headline" spellcheck="false">
<FilePreview/>
<!--File info-->
<div class="flex">
<div class="icon">
<div class="icon-preview">
<image-icon v-if="fileType === 'image'" size="21"></image-icon>
<video-icon v-if="fileType === 'video'" size="21"></video-icon>
<folder-icon v-if="fileType === 'folder'" size="21"></folder-icon>
<file-icon v-if="fileType === 'file'" size="21"></file-icon>
</div>
</div>
<div class="file-info">
<span ref="name" class="name">{{ fileInfoDetail[0].name }}</span>
<span class="mimetype text-theme" v-if="fileInfoDetail[0].mimetype">.{{ fileInfoDetail[0].mimetype }}</span>
</div>
</div>
</div>
<!--Info list-->
<ListInfo>
<ListInfoItem v-if="fileInfoDetail[0].filesize"
:title="$t('file_detail.size')"
:content="fileInfoDetail[0].filesize">
</ListInfoItem>
<ListInfoItem v-if="$checkPermission(['master']) && fileInfoDetail[0].author !== 'user'"
:title="$t('file_detail.author')"
:content="$t('file_detail.author_participant')">
</ListInfoItem>
<ListInfoItem
:title="$t('file_detail.created_at')"
:content="fileInfoDetail[0].created_at">
</ListInfoItem>
<ListInfoItem v-if="$checkPermission(['master'])"
:title="$t('file_detail.where')">
<div class="action-button" @click="moveItem">
<span>{{ fileInfoDetail[0].parent ? fileInfoDetail[0].parent.name : $t('locations.home') }}</span>
<edit-2-icon size="10" class="edit-icon"></edit-2-icon>
</div>
</ListInfoItem>
<ListInfoItem v-if="$checkPermission('master') && fileInfoDetail[0].shared"
:title="$t('file_detail.shared')">
<div class="action-button" @click="shareItemOptions">
<span>{{ sharedInfo }}</span>
<edit-2-icon size="10" class="edit-icon"></edit-2-icon>
</div>
<div class="sharelink">
<lock-icon v-if="isLocked" @click="shareItemOptions" class="lock-icon" size="17"></lock-icon>
<unlock-icon v-if="! isLocked" @click="shareItemOptions" class="lock-icon" size="17"></unlock-icon>
<CopyInput class="copy-sharelink" size="small" :item="fileInfoDetail[0]"/>
</div>
</ListInfoItem>
<ListInfoItem v-if="canShowMetaData" :title="$t('file_detail_meta.meta_data')">
<ImageMetaData />
</ListInfoItem>
</ListInfo>
</div>
</template>
<script>
import {Edit2Icon, LockIcon, UnlockIcon, ImageIcon, VideoIcon, FolderIcon, FileIcon} from 'vue-feather-icons'
import ImageMetaData from '@/components/FilesView/ImageMetaData'
import FilePreview from '@/components/FilesView/FilePreview'
import CopyInput from '@/components/Others/Forms/CopyInput'
import ListInfoItem from '@/components/Others/ListInfoItem'
import ListInfo from '@/components/Others/ListInfo'
import {mapGetters} from 'vuex'
import {events} from "@/bus"
export default {
name: 'FileInfoPanel',
components: {
ImageMetaData,
ListInfoItem,
ListInfo,
FilePreview,
FolderIcon,
UnlockIcon,
VideoIcon,
CopyInput,
ImageIcon,
FileIcon,
Edit2Icon,
LockIcon,
},
computed: {
...mapGetters(['fileInfoDetail', 'permissionOptions']),
fileType() {
return this.fileInfoDetail[0].type
},
canShowMetaData() {
return this.fileInfoDetail[0].metadata && this.fileInfoDetail[0].metadata.ExifImageWidth
},
sharedInfo() {
// Get permission title
let title = this.permissionOptions.find(option => {
return option.value === this.fileInfoDetail[0].shared.permission
})
return title ? this.$t(title.label) : this.$t('shared.can_download')
},
sharedIcon() {
switch (this.fileInfoDetail[0].shared.permission) {
case 'editor':
return 'user-edit'
break
case 'visitor':
return 'user'
break
default:
return 'download'
}
},
isLocked() {
return this.fileInfoDetail[0].shared.is_protected
}
},
methods: {
shareItemOptions() {
// Open share item popup
events.$emit('popup:open', {name: 'share-edit', item: this.fileInfoDetail[0]})
},
moveItem() {
// Move item fire popup
events.$emit("popup:open", { name: "move", item: this.fileInfoDetail});
}
}
}
</script>
<style scoped lang="scss">
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.file-info-content {
padding-bottom: 20px;
}
.file-headline {
margin-bottom: 20px;
border-radius: 8px;
.flex {
display: flex;
align-items: flex-start;
}
.icon-preview {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
text-align: center;
cursor: pointer;
white-space: nowrap;
outline: none;
border: none;
}
.file-info {
padding-left: 10px;
width: 100%;
word-break: break-all;
.name {
@include font-size(14);
font-weight: 700;
line-height: 1.4;
display: block;
color: $text;
}
.mimetype {
@include font-size(12);
font-weight: 600;
display: block;
}
}
}
.sharelink {
display: flex;
width: 100%;
align-items: center;
margin-top: 10px;
.lock-icon {
display: inline-block;
width: 15px;
margin-right: 9px;
cursor: pointer;
}
.copy-sharelink {
width: 100%;
}
}
@media (prefers-color-scheme: dark) {
.file-headline {
.file-info {
.name {
color: $dark_mode_text_primary;
}
}
}
}
</style>

View File

@@ -1,6 +1,5 @@
<template>
<div class="file-wrapper" @click.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
<!--Grid preview-->
<div class="file-wrapper" @mouseup.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
<div :draggable="canDrag" @dragstart="$emit('dragstart')" @drop="
drop()
area = false" @dragleave="dragLeave" @dragover.prevent="dragEnter" class="file-item" :class="{'is-clicked' : isClicked , 'no-clicked' : !isClicked && this.$isMobile(), 'is-dragenter': area }">
@@ -8,7 +7,7 @@
<div class="icon-item">
<!-- MultiSelecting for the mobile version -->
<div :class="{'check-select-folder' : this.item.type === 'folder', 'check-select' : this.item.type !== 'folder'}" v-if="multiSelectMode">
<div :class="{'check-select-folder' : this.item.type === 'folder', 'check-select' : this.item.type !== 'folder'}" v-if="mobileMultiSelect">
<div class="select-box" :class="{'select-box-active' : isClicked } ">
<CheckIcon v-if="isClicked" class="icon" size="17" />
</div>
@@ -58,8 +57,8 @@
</div>
</div>
<span @click.stop="showItemActions" class="show-actions" v-if="$isMobile() && ! multiSelectMode && canShowMobileOptions">
<MoreHorizontalIcon icon="ellipsis-h" size="16" class="icon-action text-theme"/>
<span @mousedown.stop="showItemActions" class="show-actions" v-if="$isMobile() && ! mobileMultiSelect && canShowMobileOptions">
<MoreHorizontalIcon icon="ellipsis-h" size="16" class="icon-action text-theme" />
</span>
</div>
</div>
@@ -84,7 +83,7 @@ export default {
},
computed: {
...mapGetters([
'FilePreviewType', 'sharedDetail', 'fileInfoDetail', 'data'
'FilePreviewType', 'sharedDetail', 'clipboard', 'entries'
]),
folderEmojiOrColor() {
@@ -102,7 +101,7 @@ export default {
},
isClicked() {
return this.fileInfoDetail.some(element => element.id === this.item.id)
return this.clipboard.some(element => element.id === this.item.id)
},
isFolder() {
return this.item.type === 'folder'
@@ -149,7 +148,7 @@ export default {
return {
area: false,
itemName: undefined,
multiSelectMode: false
mobileMultiSelect: false
}
},
methods: {
@@ -158,10 +157,10 @@ export default {
},
showItemActions() {
// Load file info detail
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('CLIPBOARD_CLEAR')
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
events.$emit('mobileMenu:show')
events.$emit('mobile-menu:show', 'file-menu')
},
dragEnter() {
if (this.item.type !== 'folder') return
@@ -181,77 +180,79 @@ export default {
if (e.ctrlKey || e.metaKey && !e.shiftKey) {
// Click + Ctrl
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
if (this.clipboard.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
} else {
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
}
} else if (e.shiftKey) {
// Click + Shift
let lastItem = this.data.indexOf(this.fileInfoDetail[this.fileInfoDetail.length - 1])
let clickedItem = this.data.indexOf(this.item)
let lastItem = this.entries.indexOf(this.clipboard[this.clipboard.length - 1])
let clickedItem = this.entries.indexOf(this.item)
// If Click + Shift + Ctrl dont remove already selected items
if (!e.ctrlKey && !e.metaKey) {
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('CLIPBOARD_CLEAR')
}
//Shift selecting from top to bottom
if (lastItem < clickedItem) {
for (let i = lastItem; i <= clickedItem; i++) {
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
}
//Shift selecting from bottom to top
} else {
for (let i = lastItem; i >= clickedItem; i--) {
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
}
}
} else {
// Click
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('CLIPBOARD_CLEAR')
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
}
}
if (!this.multiSelectMode && this.$isMobile()) {
// Open in mobile version on first click
if (this.$isMobile() && this.isFolder) {
// Go to folder
if (!this.mobileMultiSelect && this.$isMobile()) {
if (this.isFolder) {
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
} else {
this.$store.dispatch('getFolder', [{folder: this.item, back: false, init: false}])
}
}
} else {
if (this.$isMobile()) {
if (this.isImage || this.isVideo || this.isAudio) {
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
events.$emit('fileFullPreview:show')
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
this.$store.commit('CLIPBOARD_CLEAR')
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
events.$emit('file-preview:show')
}
}
}
if (this.multiSelectMode && this.$isMobile()) {
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
if (this.mobileMultiSelect && this.$isMobile()) {
if (this.clipboard.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
} else {
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
}
}
},
goToItem() {
if (this.isImage || this.isVideo || this.isAudio) {
events.$emit('fileFullPreview:show')
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
events.$emit('file-preview:show')
} else if (this.isFile || !this.isFolder && !this.isPdf && !this.isVideo && !this.isAudio && !this.isImage) {
} else if (this.isFile || !this.isFolder && !this.isVideo && !this.isAudio && !this.isImage) {
this.$downloadFile(this.item.file_url, this.item.name + '.' + this.item.mimetype)
} else if (this.isFolder) {
//Clear selected data after open another folder
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('CLIPBOARD_CLEAR')
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
@@ -284,13 +285,13 @@ export default {
})
events.$on('mobileSelecting:start', () => {
this.multiSelectMode = true
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.mobileMultiSelect = true
this.$store.commit('CLIPBOARD_CLEAR')
})
events.$on('mobileSelecting:stop', () => {
this.multiSelectMode = false
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.mobileMultiSelect = false
this.$store.commit('CLIPBOARD_CLEAR')
})
// Change item name
events.$on('change:name', (item) => {

View File

@@ -1,6 +1,5 @@
<template>
<div class="file-wrapper" @click.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
<!--List preview-->
<div class="file-wrapper" @mouseup.stop="clickedItem" @dblclick="goToItem" spellcheck="false">
<div
:draggable="canDrag"
@dragstart="$emit('dragstart')"
@@ -13,7 +12,7 @@
<transition name="slide-from-left">
<div class="check-select" v-if="mobileMultiSelect">
<div class="select-box" :class="{'select-box-active' : isClicked } ">
<CheckIcon v-if="isClicked" class="icon" size="17"/>
<CheckIcon v-if="isClicked" class="icon" size="17" />
</div>
</div>
</transition>
@@ -26,12 +25,12 @@
</span>
<!--Folder thumbnail-->
<FontAwesomeIcon v-if="isFile || (isImage && !item.thumbnail)" class="file-icon" icon="file"/>
<FontAwesomeIcon v-if="isFile || (isImage && !item.thumbnail)" class="file-icon" icon="file" />
<!--Image thumbnail-->
<img loading="lazy" v-if="isImage && item.thumbnail" class="image" :src="item.thumbnail" :alt="item.name"/>
<img loading="lazy" v-if="isImage && item.thumbnail" class="image" :src="item.thumbnail" :alt="item.name" />
<!--Else show only folder icon-->
<!--Else show only folder icon-->
<FolderIcon v-if="isFolder" :item="item" location="file-item-list" class="folder svg-color-theme" />
</div>
@@ -63,7 +62,7 @@
<!--Show item actions-->
<transition name="slide-from-right">
<div class="actions" v-if="$isMobile() && ! mobileMultiSelect">
<span @click.stop="showItemActions" class="show-actions">
<span @mousedown.stop="showItemActions" class="show-actions">
<MoreVerticalIcon size="16" class="icon-action text-theme" />
</span>
</div>
@@ -73,26 +72,32 @@
</template>
<script>
import { LinkIcon, UserPlusIcon, CheckIcon, MoreVerticalIcon } from 'vue-feather-icons'
import {LinkIcon, UserPlusIcon, CheckIcon, MoreVerticalIcon} from 'vue-feather-icons'
import FolderIcon from '@/components/FilesView/FolderIcon'
import { debounce } from 'lodash'
import { mapGetters } from 'vuex'
import { events } from '@/bus'
import {debounce} from 'lodash'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
export default {
name: 'FileItemList',
props: ['item'],
props: [
'item'
],
components: {
MoreVerticalIcon,
UserPlusIcon,
LinkIcon,
FolderIcon,
CheckIcon,
LinkIcon,
},
computed: {
...mapGetters(['FilePreviewType', 'fileInfoDetail', 'data']),
...mapGetters([
'FilePreviewType',
'clipboard',
'entries'
]),
isClicked() {
return this.fileInfoDetail.some(element => element.id === this.item.id)
return this.clipboard.some(element => element.id === this.item.id)
},
isFolder() {
return this.item.type === 'folder'
@@ -120,7 +125,7 @@ export default {
return !this.isDeleted && this.$checkPermission(['master', 'editor'])
},
timeStamp() {
return this.item.deleted_at ? this.$t('item_thumbnail.deleted_at', { time: this.item.deleted_at }) : this.item.created_at
return this.item.deleted_at ? this.$t('item_thumbnail.deleted_at', {time: this.item.deleted_at}) : this.item.created_at
},
folderItems() {
return this.item.deleted_at ? this.item.trashed_items : this.item.items
@@ -151,11 +156,10 @@ export default {
events.$emit('drop')
},
showItemActions() {
// Load file info detail
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('CLIPBOARD_CLEAR')
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
events.$emit('mobileMenu:show')
events.$emit('mobile-menu:show', 'file-menu')
},
dragEnter() {
if (this.item.type !== 'folder') return
@@ -174,89 +178,92 @@ export default {
document.getSelection().removeAllRanges();
if ((e.ctrlKey || e.metaKey) && !e.shiftKey) {
// Click + Ctrl
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
// Click + Ctrl
if (this.clipboard.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
} else {
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
}
} else if (e.shiftKey) {
// Click + Shift
let lastItem = this.data.indexOf(this.fileInfoDetail[this.fileInfoDetail.length - 1])
let clickedItem = this.data.indexOf(this.item)
// Click + Shift
let lastItem = this.entries.indexOf(this.clipboard[this.clipboard.length - 1])
let clickedItem = this.entries.indexOf(this.item)
// If Click + Shift + Ctrl dont remove already selected items
if (!e.ctrlKey && !e.metaKey) {
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('CLIPBOARD_CLEAR')
}
//Shift selecting from top to bottom
if (lastItem < clickedItem) {
for (let i = lastItem; i <= clickedItem; i++) {
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
}
//Shift selecting from bottom to top
} else {
for (let i = lastItem; i >= clickedItem; i--) {
this.$store.commit('GET_FILEINFO_DETAIL', this.data[i])
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.entries[i])
}
}
} else {
// Click
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
// Click
this.$store.commit('CLIPBOARD_CLEAR')
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
}
}
if (!this.mobileMultiSelect && this.$isMobile()) {
// Open in mobile version on first click
if (this.$isMobile() && this.isFolder) {
// Go to folder
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{ folder: this.item, back: false, init: false }])
} else {
this.$store.dispatch('getFolder', [{ folder: this.item, back: false, init: false }])
}
}
if (this.isFolder) {
if (this.$isMobile()) {
if (this.isImage || this.isVideo || this.isAudio) {
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
events.$emit('fileFullPreview:show')
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
} else {
this.$store.dispatch('getFolder', [{folder: this.item, back: false, init: false}])
}
} else {
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
this.$store.commit('CLIPBOARD_CLEAR')
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
events.$emit('file-preview:show')
}
}
}
if (this.mobileMultiSelect && this.$isMobile()) {
if (this.fileInfoDetail.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FILEINFO_DETAIL', this.item)
if (this.clipboard.some(item => item.id === this.item.id)) {
this.$store.commit('REMOVE_ITEM_FROM_CLIPBOARD', this.item)
} else {
this.$store.commit('GET_FILEINFO_DETAIL', this.item)
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.item)
}
}
},
goToItem() {
if (this.isImage || this.isVideo || this.isAudio) {
events.$emit('fileFullPreview:show')
if (this.isImage || this.isVideo || this.isAudio || this.isPdf) {
events.$emit('file-preview:show')
} else if (this.isFile || !this.isFolder && !this.isPdf && !this.isVideo && !this.isAudio && !this.isImage) {
} else if (this.isFile || !this.isFolder && !this.isVideo && !this.isAudio && !this.isImage) {
this.$downloadFile(this.item.file_url, this.item.name + '.' + this.item.mimetype)
} else if (this.isFolder) {
// Clear selected items after open another folder
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('CLIPBOARD_CLEAR')
if (this.$isThisLocation('public')) {
this.$store.dispatch('browseShared', [{ folder: this.item, back: false, init: false }])
this.$store.dispatch('browseShared', [{folder: this.item, back: false, init: false}])
} else {
this.$store.dispatch('getFolder', [{ folder: this.item, back: false, init: false }])
this.$store.dispatch('getFolder', [{folder: this.item, back: false, init: false}])
}
}
},
renameItem: debounce(function(e) {
renameItem: debounce(function (e) {
// Prevent submit empty string
if (e.target.innerText.trim() === '') return
@@ -273,7 +280,7 @@ export default {
events.$on('newFolder:focus', (id) => {
if(this.item.id === id && !this.$isMobile()) {
if (this.item.id === id && !this.$isMobile()) {
this.$refs[id].focus()
document.execCommand('selectAll')
}
@@ -281,12 +288,12 @@ export default {
events.$on('mobileSelecting:start', () => {
this.mobileMultiSelect = true
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('CLIPBOARD_CLEAR')
})
events.$on('mobileSelecting:stop', () => {
this.mobileMultiSelect = false
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('CLIPBOARD_CLEAR')
})
// Change item name
@@ -454,7 +461,7 @@ export default {
flex: 0 0 50px;
line-height: 0;
margin-right: 20px;
.folder {
width: 52px;
height: 52px;

View File

@@ -0,0 +1,179 @@
<template>
<MenuMobile name="file-menu">
<ThumbnailItem class="item-thumbnail" :item="clipboard[0]" info="metadata" />
<!--Trash location-->
<MenuMobileGroup v-if="$isThisLocation(['trash', 'trash-root']) && $checkPermission('master')">
<OptionGroup v-if="clipboard[0]">
<Option @click.native="restoreItem" :title="$t('context_menu.restore')" icon="restore" />
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="delete" />
</OptionGroup>
<OptionGroup>
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
</OptionGroup>
</MenuMobileGroup>
<!--Shared location-->
<MenuMobileGroup v-if="$isThisLocation(['shared']) && $checkPermission('master')">
<OptionGroup v-if="clipboard[0] && isFolder">
<Option @click.native="addToFavourites" :title="favouritesTitle" icon="star" />
</OptionGroup>
<OptionGroup v-if="clipboard[0]">
<Option @click.native="renameItem" :title="$t('context_menu.rename')" icon="rename" />
<Option @click.native="shareItem" :title="clipboard[0].shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
</OptionGroup>
</MenuMobileGroup>
<!--Base location for user-->
<MenuMobileGroup v-if="$isThisLocation(['base', 'participant_uploads', 'latest']) && $checkPermission('master')">
<OptionGroup v-if="clipboard[0] && isFolder">
<Option @click.native="addToFavourites" :title="favouritesTitle" icon="star" />
</OptionGroup>
<OptionGroup v-if="clipboard[0]">
<Option @click.native="renameItem" :title="$t('context_menu.rename')" icon="rename" />
<Option @click.native="moveItem" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="shareItem" :title="clipboard[0].shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
</OptionGroup>
</MenuMobileGroup>
<!--Base location for guest-->
<MenuMobileGroup v-if="$isThisLocation(['base', 'public']) && $checkPermission('editor')">
<OptionGroup>
<Option v-if="clipboard[0]" @click.native="renameItem" :title="$t('context_menu.rename')" icon="rename" />
<Option v-if="clipboard[0]" @click.native="moveItem" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="deleteItem" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
</OptionGroup>
</MenuMobileGroup>
<!--Base location for guest with visit permission-->
<MenuMobileGroup v-if="$isThisLocation(['base', 'public']) && $checkPermission('visitor')">
<OptionGroup>
<Option v-if="!isFolder" @click.native="downloadItem" :title="$t('context_menu.download')" icon="download" />
<Option v-if="isFolder" @click.native="downloadFolder" :title="$t('context_menu.zip_folder')" icon="zip-folder" />
</OptionGroup>
</MenuMobileGroup>
</MenuMobile>
</template>
<script>
import MenuMobileGroup from '@/components/Mobile/MenuMobileGroup'
import MenuMobile from '@/components/Mobile/MenuMobile'
import ThumbnailItem from '@/components/Others/ThumbnailItem'
import OptionGroup from '@/components/FilesView/OptionGroup'
import Option from '@/components/FilesView/Option'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
export default {
name: 'FileMenuMobile',
components: {
MenuMobileGroup,
MenuMobile,
ThumbnailItem,
OptionGroup,
Option,
},
computed: {
...mapGetters([
'clipboard',
'user',
]),
favourites() {
return this.user.data.relationships.favourites.data.attributes.folders
},
favouritesTitle() {
return this.isInFavourites
? this.$t('context_menu.remove_from_favourites')
: this.$t('context_menu.add_to_favourites')
},
isInFavourites() {
return this.favourites.find(el => el.id === this.clipboard[0].id)
},
isFile() {
return !this.isImage && !this.isFolder
},
isImage() {
return this.clipboard[0] && this.clipboard[0].type === 'image'
},
isFolder() {
return this.clipboard[0] && this.clipboard[0].type === 'folder'
}
},
data() {
return {
isVisible: false,
}
},
methods: {
downloadFolder() {
this.$store.dispatch('downloadFolder', this.clipboard[0])
},
moveItem() {
events.$emit('popup:open', {name: 'move', item: [this.clipboard[0]]})
},
shareItem() {
let event = this.clipboard[0].shared
? 'share-edit'
: 'share-create'
events.$emit('popup:open', {
name: event,
item: this.clipboard[0]
})
},
addToFavourites() {
if (this.favourites && !this.favourites.find(el => el.id === this.clipboard[0].id)) {
this.$store.dispatch('addToFavourites', this.clipboard[0])
} else {
this.$store.dispatch('removeFromFavourites', this.clipboard[0])
}
},
downloadItem() {
this.$downloadFile(
this.clipboard[0].file_url,
this.clipboard[0].name + '.' + this.clipboard[0].mimetype
)
},
deleteItem() {
this.$store.dispatch('deleteItem')
},
restoreItem() {
this.$store.dispatch('restoreItem', this.clipboard[0])
},
renameItem() {
events.$emit('popup:open', {name: 'rename-item', item: this.clipboard[0]})
},
}
}
</script>
<style scoped lang="scss">
@import "@assets/vuefilemanager/_variables";
@import "@assets/vuefilemanager/_mixins";
.item-thumbnail {
padding: 20px 20px 10px;
margin-bottom: 0;
}
</style>

View File

@@ -1,61 +1,77 @@
<template>
<div v-if="canBePreview" class="preview">
<img v-if="fileInfoDetail[0].type == 'image' && fileInfoDetail[0].thumbnail" :src="fileInfoDetail[0].thumbnail" :alt="fileInfoDetail[0].name" />
<audio v-else-if="fileInfoDetail[0].type == 'audio'" :src="fileInfoDetail[0].file_url" controlsList="nodownload" controls></audio>
<video v-else-if="fileInfoDetail[0].type == 'video'" controlsList="nodownload" disablePictureInPicture playsinline controls>
<source :src="fileInfoDetail[0].file_url" type="video/mp4">
</video>
</div>
<div
v-if="isFullPreview"
class="file-preview"
ref="filePreview"
tabindex="-1"
@keydown.esc="closeFilePreview"
@keydown.right="next"
@keydown.left="prev"
>
<FilePreviewToolbar />
<FilePreviewMedia />
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { includes } from 'lodash'
import FilePreviewToolbar from '@/components/FilesView/FilePreviewToolbar'
import FilePreviewMedia from '@/components/FilesView/FilePreviewMedia'
import {events} from '@/bus'
export default {
name: 'FilePreview',
computed: {
...mapGetters(['fileInfoDetail']),
canBePreview() {
return this.fileInfoDetail[0] && ! includes([
'folder', 'file'
], this.fileInfoDetail[0].type)
components: {
FilePreviewToolbar,
FilePreviewMedia,
},
data() {
return {
isFullPreview: false
}
},
methods: {
closeFilePreview() {
this.isFullPreview = false
events.$emit('showContextMenuPreview:hide')
},
next() {
events.$emit('file-preview:next')
},
prev() {
events.$emit('file-preview:prev')
}
},
updated() {
if (this.isFullPreview) {
this.$refs.filePreview.focus()
}
},
mounted() {
events.$on('file-preview:show', () => {
this.isFullPreview = true
})
events.$on('file-preview:hide', () => {
this.isFullPreview = false
})
}
}
</script>
<style scoped lang="scss">
<style lang="scss" scoped>
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.preview {
.file-preview {
width: 100%;
display: block;
margin-bottom: 7px;
height: 100%;
position: absolute;
z-index: 7;
background-color: white;
}
img {
border-radius: 4px;
overflow: hidden;
width: 100%;
object-fit: cover;
}
audio {
width: 100%;
&::-webkit-media-controls-panel {
background-color: $light_background;
}
&::-webkit-media-controls-play-button {
color: $theme;
}
}
video {
width: 100%;
height: auto;
border-radius: 3px;
@media (prefers-color-scheme: dark) {
.file-preview {
background-color: $dark_mode_background;
}
}
</style>

View File

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

View File

@@ -0,0 +1,368 @@
<template>
<div class="media-full-preview" id="mediaPreview" v-if="clipboard[0]">
<!--Arrow navigation-->
<div v-if="files.length > 1" class="navigation-arrows">
<div @click.prevent="prev" class="prev">
<chevron-left-icon size="17" />
</div>
<div @click.prevent="next" class="next">
<chevron-right-icon size="17" />
</div>
</div>
<!--File preview-->
<div class="file-wrapper-preview">
<!--Show PDF-->
<div v-if="isPDF" id="pdf-wrapper" :style="{width: documentSize + '%'}">
<pdf :src="pdfdata" v-for="i in numPages" :key="i" :resize="true" :page="i" scale="page-width" style="width:100%; margin:20px auto;" id="printable-file">
<template slot="loading">
<h1>loading content...</h1>
</template>
</pdf>
</div>
<!--Show Audio, Video and Image-->
<div v-if="!isPDF" class="file-wrapper">
<audio
v-if="isAudio"
:class="{ 'file-shadow': !$isMobile() }"
class="file audio"
:src="currentFile.file_url"
controls>
</audio>
<img
id="printable-file"
v-if="isImage"
class="file"
:class="{'file-shadow': !$isMobile() }"
:src="currentFile.file_url"
/>
<div class="video-wrapper" v-if="isVideo">
<video
:src="currentFile.file_url"
class="video"
:class="{'file-shadow': !$isMobile() }"
controlsList="nodownload"
disablePictureInPicture
playsinline
controls
autoplay
/>
</div>
</div>
</div>
</div>
</template>
<script>
import {ChevronLeftIcon, ChevronRightIcon} from 'vue-feather-icons'
import ToolbarButton from '@/components/FilesView/ToolbarButton'
import Spinner from '@/components/FilesView/Spinner'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
import pdf from 'pdfvuer'
export default {
name: 'MediaFullPreview',
components: {
ChevronRightIcon,
ChevronLeftIcon,
ToolbarButton,
Spinner,
pdf,
},
computed: {
...mapGetters([
'clipboard',
'entries',
]),
currentFile() {
return this.files[Math.abs(this.currentIndex) % this.files.length]
},
isPDF() {
return this.clipboard[0].mimetype === 'pdf'
},
isVideo() {
return this.clipboard[0].type === 'video'
},
isAudio() {
return this.clipboard[0].type === 'audio'
},
isImage() {
return this.clipboard[0].type === 'image'
}
},
data() {
return {
pdfdata: undefined,
numPages: 0,
currentIndex: 0,
files: [],
documentSize: 50,
}
},
watch: {
files() {
if (this.files.length === 0)
events.$emit('file-preview:hide')
},
currentFile() {
if (this.clipboard[0]) {
this.$store.commit('CLIPBOARD_CLEAR')
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.currentFile)
// Init pdf instance
if (this.clipboard[0].mimetype === 'pdf') {
this.getPdf()
}
}
},
clipboard() {
if (!this.clipboard[0]) {
this.currentIndex -= 1
this.$store.commit('ADD_ITEM_TO_CLIPBOARD', this.currentFile)
this.files = []
}
},
data(newValue, oldValue) {
if (newValue !== oldValue) {
this.files = []
}
},
},
methods: {
next() {
if (!this.files.length > 1) return
this.pdfdata = undefined
this.currentIndex += 1
if (this.currentIndex > this.files.length - 1) {
this.currentIndex = 0
}
},
prev() {
if (!this.files.length > 1) return
this.pdfdata = undefined
this.currentIndex -= 1
if (this.currentIndex < 0) {
this.currentIndex = this.files.length - 1
}
},
getPdf() {
this.pdfdata = undefined
this.numPages = 0
let self = this;
self.pdfdata = pdf.createLoadingTask(this.currentFile.file_url);
self.pdfdata.then(pdf => self.numPages = pdf.numPages);
},
getFilesForView() {
let requestedFile = this.clipboard[0]
this.entries.map(element => {
if (requestedFile.mimetype === 'pdf') {
if (element.mimetype === 'pdf')
this.files.push(element)
} else {
if (element.type === requestedFile.type)
this.files.push(element)
}
})
this.files.forEach((element, index) => {
if (element.id === this.clipboard[0].id) {
this.currentIndex = index
}
})
},
},
created() {
// Set zoom size
this.documentSize = window.innerWidth < 960 ? 100 : 50
events.$on('file-preview:next', () => this.next())
events.$on('file-preview:prev', () => this.prev())
events.$on('document-zoom:in', () => {
if (this.documentSize < 100)
this.documentSize += 10
})
events.$on('document-zoom:out', () => {
if (this.documentSize > 40)
this.documentSize -= 10
})
this.getFilesForView()
}
}
</script>
<style src="pdfvuer/dist/pdfvuer.css" lang="css"></style>
<style lang="scss">
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.navigation-arrows {
.prev, .next {
cursor: pointer;
position: absolute;
top: 45%;
display: flex;
justify-content: center;
color: $text;
border-radius: 50%;
text-decoration: none;
user-select: none;
filter: drop-shadow(0px 1px 0 rgba(255, 255, 255, 1));
padding: 10px;
z-index: 2;
}
.next {
right: 0;
}
.prev {
left: 0;
}
}
#pdf-wrapper {
overflow-y: scroll;
margin: 0 auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.media-full-preview {
height: calc(100% - 72px);
top: 72px;
position: relative;
background-color: white;
}
.file-wrapper-preview {
width: 100%;
height: 100%;
padding: 30px 0px;
display: flex;
overflow: hidden;
justify-content: center;
align-items: center;
background-color: white;
.file-wrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.file-shadow {
box-shadow: 0 8px 40px rgba(17, 26, 52, 0.05);
}
.file {
max-width: 100%;
max-height: 100%;
align-self: center;
}
.audio {
border-radius: 28px;
}
img {
border-radius: 4px;
}
.video-wrapper {
max-width: 1080px;
max-height: 100%;
@media (min-width: 1200px) {
& {
max-width: 800px;
}
}
@media (min-width: 1920px) and (max-width: 2560px) {
& {
max-width: 1080px;
}
}
@media (min-width: 2560px) and (max-width: 3840px) {
& {
max-width: 1440px;
}
}
@media (min-width: 3840px) {
& {
max-width: 2160px;
}
}
.video {
max-width: 100%;
max-height: 100%;
align-self: center;
}
}
}
}
@media only screen and (max-width: 960px) {
.media-full-preview {
top: 53px;
}
}
@media (prefers-color-scheme: dark) {
.navigation-arrows {
.prev, .next {
color: $light-text;
filter: drop-shadow(0px 1px 0 rgba(17, 19, 20, 1));
}
}
.file-wrapper-preview {
background-color: $dark_mode_background;
.file-wrapper {
.file-shadow {
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.1);
}
}
}
}
</style>

View File

@@ -1,319 +0,0 @@
<template>
<div class="navigation-panel" v-if="fileInfoDetail[0]">
<div class="name-wrapper">
<x-icon @click="closeFullPreview" size="22" class="icon-close hover-text-theme" />
<div class="name-count-wrapper">
<p class="title">{{ fileInfoDetail[0].name }}</p>
<span class="file-count"> ({{ showingImageIndex + ' ' + $t('pronouns.of') + ' ' + filteredFiles.length }}) </span>
</div>
<span id="fast-preview-menu" class="fast-menu-icon group" @click.stop="menuOpen" v-if="$checkPermission(['master', 'editor', 'visitor'])">
<more-horizontal-icon class="more-icon group-hover-text-theme" size="14" />
</span>
</div>
<div class="created-at-wrapper">
<p>{{ fileInfoDetail[0].filesize }}, {{ fileInfoDetail[0].created_at }}</p>
</div>
<div class="navigation-icons">
<div class="navigation-tool-wrapper">
<ToolbarButton source="download" class="mobile-hide" @click.native="downloadItem" :action="$t('actions.download')" />
<ToolbarButton v-if="canShowShareView" :class="{ 'is-inactive': canShareInView }" @click.native="shareItem" source="share" class="mobile-hide" :action="$t('actions.share')" />
<ToolbarButton v-if="this.fileInfoDetail[0].type === 'image'" source="print" :action="$t('actions.print')" @click.native="printMethod()" />
</div>
</div>
</div>
</template>
<script>
import { events } from '@/bus'
import { mapGetters } from 'vuex'
import { XIcon, MoreHorizontalIcon } from 'vue-feather-icons'
import ToolbarButton from '@/components/FilesView/ToolbarButton'
export default {
name: 'FilePreviewNavigationPanel',
components: { ToolbarButton, XIcon, MoreHorizontalIcon },
computed: {
...mapGetters(['fileInfoDetail', 'data']),
filteredFiles() {
let files = []
this.data.filter((element) => {
if (element.type == this.fileInfoDetail[0].type) {
files.push(element)
}
})
return files
},
showingImageIndex() {
let activeIndex = ''
this.filteredFiles.filter((element, index) => {
if (element.id === this.fileInfoDetail[0].id) {
activeIndex = index + 1
}
})
return activeIndex
},
canShowShareView() {
return this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared'])
},
canShareInView() {
return ! this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared'])
}
},
data() {
return {
showContextMenu: false
}
},
methods: {
printMethod() {
var tab = document.getElementById('image')
var win = window.open('', '', 'height=700,width=700')
win.document.write(tab.outerHTML)
win.document.close()
win.print()
},
downloadItem() {
// Download file
this.$downloadFile(this.fileInfoDetail[0].file_url, this.fileInfoDetail[0].name + '.' + this.fileInfoDetail[0].mimetype)
},
shareItem() {
if (this.fileInfoDetail[0].shared) {
events.$emit('popup:open', {
name: 'share-edit',
item: this.fileInfoDetail[0]
})
} else {
events.$emit('popup:open', {
name: 'share-create',
item: this.fileInfoDetail[0]
})
}
},
menuOpen() {
if (this.$isMobile()) {
events.$emit('mobileMenu:show', 'showFromMediaPreview')
} else {
events.$emit('showContextMenuPreview:show', this.fileInfoDetail[0])
}
},
closeFullPreview() {
events.$emit('fileFullPreview:hide')
events.$emit('showContextMenuPreview:hide')
}
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.name-wrapper {
width: 33%;
height: 22px;
display: flex;
position: relative;
align-items: center;
flex-grow: 1;
align-self: center;
white-space: nowrap;
.name-count-wrapper {
margin-left: 6px;
margin-right: 6px;
.file-count {
@include font-size(15);
line-height: 1;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
align-self: center;
color: $text;
}
.title {
@include font-size(15);
max-width: 250px;
line-height: 1;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
color: $text;
}
@media (max-width: 570px) {
.title{
max-width: 180px;
@include font-size(17);
}
.file-count {
@include font-size(17);
}
}
}
.icon-close {
min-width: 22px;
padding: 1px 4px;
border-radius: 6px;
vertical-align: middle;
cursor: pointer;
@include transition(150ms);
&:hover {
background: $light_background;
line {
color: inherit;
}
}
}
.fast-menu-icon {
height: 24px;
display: flex;
align-items: center;
vertical-align: middle;
padding: 1px 4px;
line-height: 0;
border-radius: 3px;
cursor: pointer;
@include transition(150ms);
svg circle {
@include transition(150ms);
}
&:hover {
background: $light_background;
svg circle {
color: inherit;
}
}
.more-icon {
vertical-align: middle;
cursor: pointer;
}
}
}
.context-menu {
min-width: 250px;
position: absolute;
z-index: 99;
box-shadow: $shadow;
background: white;
border-radius: 8px;
overflow: hidden;
top: 29px;
&.showed {
display: block;
}
}
.created-at-wrapper {
width: 33%;
display: flex;
text-align: center;
justify-content: center;
p {
display: flex;
align-items: center;
@include font-size(11);
}
}
.navigation-icons {
width: 33%;
text-align: right;
.navigation-tool-wrapper {
margin-left: 28px;
display: inline-block;
vertical-align: middle;
}
.button {
margin-left: 5px;
&:hover {
background: $light_background;
}
}
}
.navigation-panel {
height: 63px;
width: 100%;
padding: 10px 15px;
display: flex;
position: absolute;
z-index: 8;
align-items: center;
background-color: white;
color: $text;
}
@media (max-width: 960px) {
.context-menu {
.name-wrapper {
width: 67%;
}
}
.navigation-icons {
display: none;
}
.navigation-panel {
height: 53px;
padding: 15px;
}
.created-at-wrapper {
display: none;
}
.name-wrapper {
justify-content: space-between;
flex-direction: row-reverse;
width: 100%;
}
}
@media (prefers-color-scheme: dark) {
.navigation-panel {
background-color: $dark_mode_background;
color: $dark_mode_text_primary;
.icon-close {
color: $dark_mode_text_primary;
&:hover {
background-color: $dark_mode_background;
}
}
.fast-menu-icon:hover {
background: $dark_mode_background;
}
}
.name-wrapper {
.title,
.file-count {
color: $dark_mode_text_primary !important;
}
}
.navigation-icons {
.button:hover {
background: $dark_mode_background;
}
}
}
</style>

View File

@@ -0,0 +1,357 @@
<template>
<div class="navigation-panel" v-if="clipboard[0]">
<div class="name-wrapper">
<x-icon @click="closeFullPreview" size="22" class="icon-close hover-text-theme" />
<div class="name-count-wrapper">
<p class="title">{{ clipboard[0].name }}</p>
<span class="file-count"> ({{ showingImageIndex + ' ' + $t('pronouns.of') + ' ' + files.length }}) </span>
</div>
<span @click.stop="menuOpen" id="fast-preview-menu" class="fast-menu-icon group">
<more-horizontal-icon class="more-icon group-hover-text-theme" size="14" />
</span>
</div>
<div class="created-at-wrapper">
<p>{{ clipboard[0].filesize }}, {{ clipboard[0].created_at }}</p>
</div>
<div class="navigation-icons">
<div v-if="isPdf" class="navigation-tool-wrapper">
<ToolbarButton @click.native="increaseSizeOfPDF" source="zoom-in" :action="$t('pdf_zoom_in')" />
<ToolbarButton @click.native="decreaseSizeOfPDF" source="zoom-out" :action="$t('pdf_zoom_out')" />
</div>
<div class="navigation-tool-wrapper">
<ToolbarButton @click.native="downloadItem" class="mobile-hide" source="download" :action="$t('actions.download')" />
<ToolbarButton v-if="canShareItem" @click.native="shareItem" class="mobile-hide" :class="{ 'is-inactive': !canShareItem }" source="share" :action="$t('actions.share')" />
<ToolbarButton v-if="isImage" @click.native="printMethod()" source="print" :action="$t('actions.print')" />
</div>
</div>
</div>
</template>
<script>
import ToolbarButton from '@/components/FilesView/ToolbarButton'
import {XIcon, MoreHorizontalIcon} from 'vue-feather-icons'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
export default {
name: 'FilePreviewToolbar',
components: {
MoreHorizontalIcon,
ToolbarButton,
XIcon,
},
computed: {
...mapGetters([
'clipboard',
'entries'
]),
isImage() {
return this.clipboard[0].type === 'image'
},
isPdf() {
return this.clipboard[0].mimetype === 'pdf'
},
files() {
let files = []
this.entries.map(element => {
if (this.clipboard[0].mimetype === 'pdf') {
if (element.mimetype === 'pdf')
files.push(element)
} else {
if (element.type === this.clipboard[0].type)
files.push(element)
}
})
return files
},
showingImageIndex() {
let activeIndex = undefined
this.files.forEach((element, index) => {
if (element.id === this.clipboard[0].id) {
activeIndex = index + 1
}
})
return activeIndex
},
canShareItem() {
return this.$isThisLocation([
'base', 'participant_uploads', 'latest', 'shared'
])
},
},
methods: {
increaseSizeOfPDF() {
events.$emit('document-zoom:in')
},
decreaseSizeOfPDF() {
events.$emit('document-zoom:out')
},
printMethod() {
let tab = document.getElementById('printable-file')
let win = window.open('', '', 'height=700,width=700')
win.document.write(tab.outerHTML)
win.document.close()
win.print()
},
downloadItem() {
this.$downloadFile(
this.clipboard[0].file_url,
this.clipboard[0].name + '.' + this.clipboard[0].mimetype
)
},
shareItem() {
let event = this.clipboard[0].shared
? 'share-edit'
: 'share-create'
events.$emit('popup:open', {
name: event,
item: this.clipboard[0]
})
},
menuOpen() {
if (this.$isMobile()) {
events.$emit('mobile-menu:show', 'file-menu')
} else {
events.$emit('showContextMenuPreview:show', this.clipboard[0])
}
},
closeFullPreview() {
events.$emit('file-preview:hide')
events.$emit('showContextMenuPreview:hide')
}
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.name-wrapper {
width: 33%;
height: 22px;
display: flex;
position: relative;
align-items: center;
flex-grow: 1;
align-self: center;
white-space: nowrap;
.name-count-wrapper {
margin-left: 6px;
margin-right: 6px;
.file-count {
@include font-size(15);
line-height: 1;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
align-self: center;
color: $text;
}
.title {
@include font-size(15);
max-width: 250px;
line-height: 1;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
color: $text;
}
@media (max-width: 570px) {
.title {
max-width: 180px;
@include font-size(17);
}
.file-count {
@include font-size(17);
}
}
}
.icon-close {
min-width: 22px;
padding: 1px 4px;
border-radius: 6px;
vertical-align: middle;
cursor: pointer;
@include transition(150ms);
&:hover {
background: $light_background;
line {
color: inherit;
}
}
}
.fast-menu-icon {
height: 24px;
display: flex;
align-items: center;
vertical-align: middle;
padding: 1px 4px;
line-height: 0;
border-radius: 3px;
cursor: pointer;
@include transition(150ms);
svg circle {
@include transition(150ms);
}
&:hover {
background: $light_background;
svg circle {
color: inherit;
}
}
.more-icon {
vertical-align: middle;
cursor: pointer;
}
}
}
.context-menu {
min-width: 250px;
position: absolute;
z-index: 99;
box-shadow: $shadow;
background: white;
border-radius: 8px;
overflow: hidden;
top: 29px;
&.showed {
display: block;
}
}
.created-at-wrapper {
width: 33%;
display: flex;
text-align: center;
justify-content: center;
p {
display: flex;
align-items: center;
@include font-size(11);
}
}
.navigation-icons {
width: 33%;
text-align: right;
.navigation-tool-wrapper {
margin-left: 28px;
display: inline-block;
vertical-align: middle;
}
.button {
margin-left: 5px;
&:hover {
background: $light_background;
}
}
}
.navigation-panel {
height: 63px;
width: 100%;
padding: 10px 15px;
display: flex;
position: absolute;
z-index: 8;
align-items: center;
background-color: white;
color: $text;
}
@media (max-width: 960px) {
.context-menu {
.name-wrapper {
width: 67%;
}
}
.navigation-icons {
display: none;
}
.navigation-panel {
height: 53px;
padding: 15px;
}
.created-at-wrapper {
display: none;
}
.name-wrapper {
justify-content: space-between;
flex-direction: row-reverse;
width: 100%;
}
}
@media (prefers-color-scheme: dark) {
.navigation-panel {
background-color: $dark_mode_background;
color: $dark_mode_text_primary;
.icon-close {
color: $dark_mode_text_primary;
&:hover {
background-color: $dark_mode_background;
}
}
.fast-menu-icon:hover {
background: $dark_mode_background;
}
}
.name-wrapper {
.title,
.file-count {
color: $dark_mode_text_primary !important;
}
}
.navigation-icons {
.button:hover {
background: $dark_mode_background;
}
}
}
</style>

View File

@@ -0,0 +1,22 @@
<template>
<MenuMobile name="file-sorting">
<MenuMobileGroup>
<FileSortingOptions />
</MenuMobileGroup>
</MenuMobile>
</template>
<script>
import FileSortingOptions from '@/components/FilesView/FileSortingOptions'
import MenuMobileGroup from '@/components/Mobile/MenuMobileGroup'
import MenuMobile from '@/components/Mobile/MenuMobile'
export default {
name: 'FilterSortingMobile',
components: {
FileSortingOptions,
MenuMobileGroup,
MenuMobile,
},
}
</script>

View File

@@ -1,10 +1,10 @@
<template>
<div class="menu-options" id="menu-list">
<OptionGroup class="menu-option-group">
<div>
<OptionGroup>
<Option v-if="isList" @click.native="changePreview('grid')" :title="$t('preview_sorting.grid_view')" icon="grid" />
<Option v-if="isGrid" @click.native="changePreview('list')" :title="$t('preview_sorting.list_view')" icon="list" />
</OptionGroup>
<OptionGroup class="menu-option-group">
<OptionGroup>
<Option @click.native.stop="sort('created_at')" :title="$t('preview_sorting.sort_date')" icon="calendar" />
<Option @click.native.stop="sort('name')" :title="$t('preview_sorting.sort_alphabet')" icon="alphabet" />
</OptionGroup>
@@ -19,25 +19,20 @@
import OptionGroup from '@/components/FilesView/OptionGroup'
import Option from '@/components/FilesView/Option'
import { CalendarIcon, ListIcon, GridIcon, ArrowUpIcon, CheckIcon } from 'vue-feather-icons'
import AlphabetIcon from '@/components/FilesView/Icons/AlphabetIcon'
import { ArrowUpIcon } from 'vue-feather-icons'
import { mapGetters } from 'vuex'
import { events } from '@/bus'
export default {
name: 'SortingAndPreviewMenu',
name: 'FileSortingOptions',
components: {
OptionGroup,
Option,
CalendarIcon,
AlphabetIcon,
ArrowUpIcon,
CheckIcon,
ListIcon,
GridIcon
Option,
},
computed: {
...mapGetters(['FilePreviewType']),
...mapGetters([
'FilePreviewType'
]),
isGrid() {
return this.FilePreviewType === 'grid'
},
@@ -55,7 +50,6 @@ export default {
},
methods: {
sort(field) {
this.filter.field = field
// Set sorting direction
@@ -74,16 +68,10 @@ export default {
this.$getDataByLocation()
},
changePreview(previewType) {
this.$store.dispatch('changePreviewType', previewType)
if (this.$isMobile())
events.$emit('mobileSortingAndPreview', false)
events.$emit('mobileSortingAndPreviewVignette', this.mobileSortingAndPreview)
}
},
mounted() {
let sorting = JSON.parse(localStorage.getItem('sorting'))
// Set default sorting if in not setup in LocalStorage
@@ -92,89 +80,3 @@ export default {
}
}
</script>
<style scoped lang="scss">
@import "@assets/vuefilemanager/_variables";
@import "@assets/vuefilemanager/_mixins";
.show-icon {
margin-left: auto;
max-height: 19px;
.arrow-down {
@include transform(rotate(180deg));
}
}
.menu-option {
display: flex;
.icon {
margin-right: 20px;
line-height: 0;
}
.text-label {
@include font-size(16);
}
}
.sorting-preview {
min-width: 250px;
position: absolute;
z-index: 99;
box-shadow: $shadow;
background: white;
border-radius: 8px;
overflow: hidden;
right: 66px;
top: 63px;
&.showed {
display: block;
}
}
.menu-options {
list-style: none;
width: 100%;
margin: 0;
padding: 0;
.menu-option-group {
padding: 5px 0;
border-bottom: 1px solid $light_mode_border;
&:first-child {
padding-top: 0;
}
&:last-child {
padding-bottom: 0;
border-bottom: none;
}
}
.menu-option {
white-space: nowrap;
font-weight: 700;
@include font-size(14);
padding: 15px 20px;
cursor: pointer;
width: 100%;
color: $text;
}
}
@media (prefers-color-scheme: dark) {
.menu-options {
.menu-option-group {
border-color: $dark_mode_border_color;
}
.menu-option {
color: $dark_mode_text_primary;
}
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<svg class="preview-list-icon" fill="none" stroke="currentColor" stroke-width="1.5" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" width="15px" height="15px" viewBox="0 0 20 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg class="preview-list-icon" fill="none" stroke="currentColor" stroke-width="1.5" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" width="20px" height="20px" viewBox="0 0 20 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="9.77777778" y="0" width="6.22222222" height="6.22222222"></rect>
<rect x="9.77777778" y="9.77777778" width="6.22222222" height="6.22222222"></rect>
<line x1="0" y1="2" x2="6" y2="2"></line>

View File

@@ -1,108 +1,109 @@
<template>
<div>
<ul class="meta-data-list">
<li v-if="fileInfoDetail.metadata.DateTimeOriginal">
<li v-if="clipboard.metadata.DateTimeOriginal">
<span>{{ $t('file_detail_meta.time_data') }}</span>
<b>{{ fileInfoDetail.metadata.DateTimeOriginal }}</b>
<b>{{ clipboard.metadata.DateTimeOriginal }}</b>
</li>
<li v-if="fileInfoDetail.metadata.Artist">
<li v-if="clipboard.metadata.Artist">
<span>{{ $t('file_detail_meta.author') }}</span>
<b>{{ fileInfoDetail.metadata.Artist }}</b>
<b>{{ clipboard.metadata.Artist }}</b>
</li>
<li v-if="fileInfoDetail.metadata.ExifImageWidth && fileInfoDetail.metadata.ExifImageLength">
<li v-if="clipboard.metadata.ExifImageWidth && clipboard.metadata.ExifImageLength">
<span>{{ $t('file_detail_meta.dimension') }}</span>
<b>{{ fileInfoDetail.metadata.ExifImageWidth }}x{{ fileInfoDetail.metadata.ExifImageLength }}</b>
<b>{{ clipboard.metadata.ExifImageWidth }}x{{ clipboard.metadata.ExifImageLength }}</b>
</li>
<li v-if="fileInfoDetail.metadata.XResolution && fileInfoDetail.metadata.YResolution">
<li v-if="clipboard.metadata.XResolution && clipboard.metadata.YResolution">
<span>{{ $t('file_detail_meta.resolution') }}</span>
<b>{{ fileInfoDetail.metadata.XResolution }}x{{ fileInfoDetail.metadata.YResolution }}</b>
<b>{{ clipboard.metadata.XResolution }}x{{ clipboard.metadata.YResolution }}</b>
</li>
<li v-if="fileInfoDetail.metadata.ColorSpace">
<li v-if="clipboard.metadata.ColorSpace">
<span> {{ $t('file_detail_meta.color_space') }}</span>
<b>{{ fileInfoDetail.metadata.ColorSpace}}</b>
<b>{{ clipboard.metadata.ColorSpace }}</b>
</li>
<!--TODO: Colour profile:sRGB IEC61966-2.1-->
<!--TODO: Colour profile:sRGB IEC61966-2.1-->
<li v-if="fileInfoDetail.metadata.Make">
<li v-if="clipboard.metadata.Make">
<span>{{ $t('file_detail_meta.make') }}</span>
<b>{{ fileInfoDetail.metadata.Make }}</b>
<b>{{ clipboard.metadata.Make }}</b>
</li>
<li v-if="fileInfoDetail.metadata.Model">
<li v-if="clipboard.metadata.Model">
<span>{{ $t('file_detail_meta.model') }}</span>
<b>{{ fileInfoDetail.metadata.Model }}</b>
<b>{{ clipboard.metadata.Model }}</b>
</li>
<li v-if="fileInfoDetail.metadata.ApertureValue">
<li v-if="clipboard.metadata.ApertureValue">
<span>{{ $t('file_detail_meta.aperture_value') }}</span>
<b v-html="parseInt(fileInfoDetail.metadata.ApertureValue) / 100"></b>
<b v-html="parseInt(clipboard.metadata.ApertureValue) / 100"></b>
</li>
<li v-if="fileInfoDetail.metadata.ExposureTime">
<li v-if="clipboard.metadata.ExposureTime">
<span>{{ $t('file_detail_meta.exposure') }}</span>
<b>{{ fileInfoDetail.metadata.ExposureTime }}</b>
<b>{{ clipboard.metadata.ExposureTime }}</b>
</li>
<li v-if="fileInfoDetail.metadata.FocalLength">
<li v-if="clipboard.metadata.FocalLength">
<span>{{ $t('file_detail_meta.focal') }}</span>
<b>{{ fileInfoDetail.metadata.FocalLength }}</b>
<b>{{ clipboard.metadata.FocalLength }}</b>
</li>
<li v-if="fileInfoDetail.metadata.ISOSpeedRatings">
<li v-if="clipboard.metadata.ISOSpeedRatings">
<span>{{ $t('file_detail_meta.iso') }}</span>
<b>{{ fileInfoDetail.metadata.ISOSpeedRatings }}</b>
<b>{{ clipboard.metadata.ISOSpeedRatings }}</b>
</li>
<li v-if="fileInfoDetail.metadata.COMPUTED.ApertureFNumber">
<li v-if="clipboard.metadata.COMPUTED.ApertureFNumber">
<span>{{ $t('file_detail_meta.aperature') }}</span>
<b>{{ fileInfoDetail.metadata.COMPUTED.ApertureFNumber }}</b>
<b>{{ clipboard.metadata.COMPUTED.ApertureFNumber }}</b>
</li>
<li v-if="fileInfoDetail.metadata.COMPUTED.CCDWidth">
<li v-if="clipboard.metadata.COMPUTED.CCDWidth">
<span>{{ $t('file_detail_meta.camera_lens') }}</span>
<b>{{ fileInfoDetail.metadata.COMPUTED.CCDWidth }}</b>
<b>{{ clipboard.metadata.COMPUTED.CCDWidth }}</b>
</li>
<li v-if="fileInfoDetail.metadata.GPSLongitude">
<li v-if="clipboard.metadata.GPSLongitude">
<span>{{ $t('file_detail_meta.longitude') }}</span>
<b>{{ formatGps(fileInfoDetail.metadata.GPSLongitude,fileInfoDetail.metadata.GPSLongitudeRef) }}</b>
</li>
<li v-if="fileInfoDetail.metadata.GPSLatitude">
<span>{{ $t('file_detail_meta.latitude') }}</span>
<b>{{ formatGps(fileInfoDetail.metadata.GPSLatitude, fileInfoDetail.metadata.GPSLatitudeRef) }}</b>
<b>{{ formatGps(clipboard.metadata.GPSLongitude, clipboard.metadata.GPSLongitudeRef) }}</b>
</li>
<li v-if="clipboard.metadata.GPSLatitude">
<span>{{ $t('file_detail_meta.latitude') }}</span>
<b>{{ formatGps(clipboard.metadata.GPSLatitude, clipboard.metadata.GPSLatitudeRef) }}</b>
</li>
</ul>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import {mapGetters} from 'vuex'
import {split} from 'lodash'
export default {
name: 'ImageMetaData',
computed: {
fileInfoDetail() {
return this.$store.getters.fileInfoDetail[0]
},
},
methods: {
formatGps(location, ref) {
let data = []
location.forEach(location => {
data.push(split(location , '/' , 2)[0])
})
return `${data[0]}° ${data[1]}' ${data[2].substr(0,4) / 100}" ${ref} `
}
},
name: 'ImageMetaData',
computed: {
clipboard() {
return this.$store.getters.clipboard[0]
},
},
methods: {
formatGps(location, ref) {
let data = []
location.forEach(location => {
data.push(split(location, '/', 2)[0])
})
return `${data[0]}° ${data[1]}' ${data[2].substr(0, 4) / 100}" ${ref} `
}
},
}
</script>
@@ -111,33 +112,33 @@ export default {
@import '@assets/vuefilemanager/_mixins';
.meta-data-list {
list-style: none;
padding: 0px;
margin: 0px;
list-style: none;
padding: 0px;
margin: 0px;
li {
display: flex;
justify-content: space-between;
padding: 9px 0;
border-bottom: 1px solid $light_mode_border;
li {
display: flex;
justify-content: space-between;
padding: 9px 0;
border-bottom: 1px solid $light_mode_border;
b, span {
@include font-size(14);
color: $text;
}
}
b, span {
@include font-size(14);
color: $text;
}
}
}
@media (prefers-color-scheme: dark) {
.meta-data-list {
li {
border-color: $dark_mode_border_color;
.meta-data-list {
li {
border-color: $dark_mode_border_color;
b, span {
color: $dark_mode_text_primary !important;
}
}
}
b, span {
color: $dark_mode_text_primary !important;
}
}
}
}
</style>

View File

@@ -0,0 +1,186 @@
<template>
<div class="info-wrapper">
<!--Is empty clipboard-->
<EmptyMessage
v-if="isEmpty"
:message="$t('messages.nothing_to_preview')"
icon="eye-off"
/>
<!--Multiple item selection-->
<div v-if="! isSingleFile && !isEmpty" class="info-headline">
<TitlePreview
icon="check-square"
:title="$t('file_detail.selected_multiple')"
:subtitle="this.clipboard.length + ' ' + $tc('file_detail.items', this.clipboard.length)"
/>
</div>
<!--Single file preview-->
<div v-if="isSingleFile && !isEmpty" class="info-headline">
<FilePreviewDetail />
<TitlePreview
:icon="clipboard[0].type"
:title="clipboard[0].name"
:subtitle="clipboard[0].mimetype"
/>
</div>
<!--File info-->
<ListInfo v-if="isSingleFile && !isEmpty">
<!--Filesize-->
<ListInfoItem
v-if="singleFile.filesize"
:title="$t('file_detail.size')"
:content="singleFile.filesize"
/>
<!--Participant-->
<ListInfoItem
v-if="$checkPermission(['master']) && singleFile.author !== 'user'"
:title="$t('file_detail.author')"
:content="$t('file_detail.author_participant')"
/>
<!--Created At-->
<ListInfoItem
:title="$t('file_detail.created_at')"
:content="singleFile.created_at"
/>
<!--Location-->
<ListInfoItem
v-if="$checkPermission(['master'])"
:title="$t('file_detail.where')"
>
<div class="action-button" @click="openMoveOptions">
<span>{{ singleFile.parent ? singleFile.parent.name : $t('locations.home') }}</span>
<edit-2-icon size="10" class="edit-icon" />
</div>
</ListInfoItem>
<!--Shared-->
<ListInfoItem
v-if="$checkPermission('master') && singleFile.shared"
:title="$t('file_detail.shared')"
>
<div @click="openShareOptions" class="action-button">
<span>{{ sharedInfo }}</span>
<edit-2-icon size="10" class="edit-icon" />
</div>
<div class="share-link">
<lock-icon v-if="isLocked" @click="openShareOptions" class="lock-icon" size="17" />
<unlock-icon v-if="! isLocked" @click="openShareOptions" class="lock-icon" size="17" />
<CopyInput :item="singleFile" class="copy-share-link" size="small" />
</div>
</ListInfoItem>
<!--Metadata-->
<ListInfoItem
v-if="canShowMetaData"
:title="$t('file_detail_meta.meta_data')"
>
<ImageMetaData />
</ListInfoItem>
</ListInfo>
</div>
</template>
<script>
import FilePreviewDetail from '@/components/Others/FilePreviewDetail'
import {Edit2Icon, LockIcon, UnlockIcon} from 'vue-feather-icons'
import ImageMetaData from '@/components/FilesView/ImageMetaData'
import EmptyMessage from '@/components/FilesView/EmptyMessage'
import TitlePreview from '@/components/FilesView/TitlePreview'
import CopyInput from '@/components/Others/Forms/CopyInput'
import ListInfoItem from '@/components/Others/ListInfoItem'
import ListInfo from '@/components/Others/ListInfo'
import {mapGetters} from 'vuex'
import {events} from "@/bus"
export default {
name: 'InfoSidebar',
components: {
FilePreviewDetail,
ImageMetaData,
EmptyMessage,
TitlePreview,
ListInfoItem,
UnlockIcon,
CopyInput,
Edit2Icon,
LockIcon,
ListInfo,
},
computed: {
...mapGetters([
'permissionOptions',
'clipboard',
]),
isEmpty() {
return this.clipboard.length === 0
},
isSingleFile() {
return this.clipboard.length === 1
},
singleFile() {
return this.clipboard[0]
},
canShowMetaData() {
return this.clipboard[0].metadata && this.clipboard[0].metadata.ExifImageWidth
},
isLocked() {
return this.clipboard[0].shared.is_protected
},
sharedInfo() {
let title = this.permissionOptions.find(option => {
return option.value === this.clipboard[0].shared.permission
})
return title ? this.$t(title.label) : this.$t('shared.can_download')
},
},
methods: {
openShareOptions() {
events.$emit('popup:open', {name: 'share-edit', item: this.clipboard[0]})
},
openMoveOptions() {
events.$emit("popup:open", {name: "move", item: this.clipboard});
}
}
}
</script>
<style scoped lang="scss">
.info-wrapper {
padding-bottom: 20px;
height: 100%;
}
.info-headline {
margin-bottom: 20px;
border-radius: 8px;
}
.share-link {
display: flex;
width: 100%;
align-items: center;
margin-top: 10px;
.lock-icon {
display: inline-block;
width: 15px;
margin-right: 9px;
cursor: pointer;
}
.copy-share-link {
width: 100%;
}
}
</style>

View File

@@ -1,236 +0,0 @@
<template>
<div class="media-full-preview" id="mediaPreview" v-if="this.isMedia && fileInfoDetail[0]">
<div class="file-wrapper-preview" v-for="i in [currentIndex]" :key="i">
<div class="file-wrapper">
<audio class="file audio" :class="{ 'file-shadow': !isMobileDevice }" v-if="fileInfoDetail[0].type == 'audio'" :src="currentFile.file_url" controlsList="nodownload" controls></audio>
<img v-if="fileInfoDetail[0].type === 'image' && currentFile.thumbnail" class="file" :class="{ 'file-shadow': !isMobileDevice }" id="image" :src="currentFile.file_url" />
<div class="video-wrapper" v-if="fileInfoDetail[0].type === 'video' && currentFile.file_url">
<video :src="currentFile.file_url" class="video" :class="{ 'file-shadow': !isMobileDevice }" controlsList="nodownload" disablePictureInPicture playsinline controls autoplay />
</div>
</div>
</div>
</div>
</template>
<script>
import { events } from '@/bus'
import { mapGetters } from 'vuex'
import ToolbarButton from '@/components/FilesView/ToolbarButton'
import Spinner from '@/components/FilesView/Spinner'
export default {
name: 'MediaFullPreview',
components: { ToolbarButton, Spinner },
computed: {
...mapGetters(['fileInfoDetail', 'data']),
isMobileDevice() {
return this.$isMobile()
},
currentFile: function() {
return this.sliderFile[Math.abs(this.currentIndex) % this.sliderFile.length]
},
isMedia() {
return this.fileInfoDetail[0] === 'image' || 'video' || 'audio'
},
canShareInView() {
return !this.$isThisLocation(['base', 'participant_uploads', 'latest', 'shared', 'public'])
}
},
data() {
return {
currentIndex: 1,
sliderFile: []
// loaded: false
}
},
watch: {
sliderFile() {
//Close file preview after delete all items
if (this.sliderFile.length == 0) {
events.$emit('fileFullPreview:hide')
}
},
currentFile() {
//Handle actual view image in fileInfoDetail
if (this.fileInfoDetail[0]) {
this.$store.commit('CLEAR_FILEINFO_DETAIL')
this.$store.commit('GET_FILEINFO_DETAIL', this.currentFile)
events.$emit('actualShowingImage:ContextMenu', this.currentFile)
// this.loaded = false
}
},
fileInfoDetail() {
//File delete handling - show next image after delete one
if (!this.fileInfoDetail[0]) {
this.currentIndex = this.currentIndex - 1
this.$store.commit('GET_FILEINFO_DETAIL', this.currentFile)
this.sliderFile = []
this.filteredFiles()
}
},
data(newValue, oldValue) {
//Move item handling
if (newValue != oldValue) {
this.sliderFile = []
this.filteredFiles()
}
}
},
methods: {
filteredFiles() {
this.data.filter((element) => {
if (element.type == this.fileInfoDetail[0].type) {
this.sliderFile.push(element)
}
})
this.choseActiveFile()
},
choseActiveFile() {
this.sliderFile.forEach((element, index) => {
if (element.id == this.fileInfoDetail[0].id) {
this.currentIndex = index
}
})
}
},
mounted() {
if (this.sliderFile.length > 1) {
events.$on('filePreviewAction:next', () => {
this.currentIndex += 1
this.slideType = 'next'
if (this.currentIndex > this.sliderFile.length - 1) {
this.currentIndex = 0
}
})
events.$on('filePreviewAction:prev', () => {
this.slideType = 'prev'
this.currentIndex -= 1
if (this.currentIndex < 0) {
this.currentIndex = this.sliderFile.length - 1
}
})
}
},
created() {
this.filteredFiles()
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.media-full-preview {
height: calc(100% - 72px);
top: 72px;
position: relative;
background-color: white;
}
.navigation-panel {
width: 100%;
height: 7%;
display: flex;
align-items: center;
padding: 20px;
justify-content: space-between;
background-color: $light-background;
color: $text;
.icon-close {
color: $text;
@include font-size(21);
&:hover {
color: $theme;
}
}
}
.loading-spinner {
position: relative;
}
.file-wrapper-preview {
width: 100%;
height: 100%;
padding: 30px 0px;
display: flex;
overflow: hidden;
justify-content: center;
align-items: center;
background-color: white;
.file-wrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.file-shadow {
box-shadow: 0 8px 40px rgba(17, 26, 52, 0.05);
}
.file {
max-width: 100%;
max-height: 100%;
align-self: center;
}
.audio {
border-radius: 28px;
}
img {
border-radius: 4px;
}
.video-wrapper {
max-width: 1080px;
max-height: 100%;
@media (min-width: 1200px) {
& {
max-width: 800px;
}
}
@media (min-width: 1920px) and (max-width: 2560px) {
& {
max-width: 1080px;
}
}
@media (min-width: 2560px) and (max-width: 3840px) {
& {
max-width: 1440px;
}
}
@media (min-width: 3840px) {
& {
max-width: 2160px;
}
}
.video {
max-width: 100%;
max-height: 100%;
align-self: center;
}
}
}
}
@media (prefers-color-scheme: dark) {
.file-wrapper-preview {
background-color: $dark_mode_background;
.file-wrapper {
.file-shadow {
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.1);
}
}
}
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<button class="mobile-action-button">
<div class="flex">
<filter-icon v-if="icon === 'filter'" size="15" class="icon dark-text-theme" />
<credit-card-icon v-if="icon === 'credit-card'" size="15" class="icon dark-text-theme" />
<folder-plus-icon v-if="icon === 'folder-plus'" size="15" class="icon dark-text-theme" />
<list-icon v-if="icon === 'th-list'" size="15" class="icon dark-text-theme" />
@@ -12,7 +13,7 @@
<x-square-icon v-if="icon === 'x-square'" size="15" class="icon dark-text-theme" />
<check-icon v-if="icon === 'check'" size="15" class="icon dark-text-theme" />
<dollar-sign-icon v-if="icon === 'dollar-sign'" size="15" class="icon dark-text-theme" />
<sorting-and-preview-icon v-if="icon === 'preview-sorting'" size="15" class="icon dark-text-theme preview-sorting" />
<sorting-icon v-if="icon === 'preview-sorting'" class="icon dark-text-theme preview-sorting" />
<span class="label">
<slot></slot>
</span>
@@ -21,8 +22,8 @@
</template>
<script>
import { DollarSignIcon, CheckIcon, XSquareIcon, CheckSquareIcon, FolderPlusIcon, ListIcon, GridIcon, TrashIcon, UserPlusIcon, PlusIcon, CreditCardIcon } from 'vue-feather-icons'
import SortingAndPreviewIcon from '@/components/FilesView/Icons/SortingAndPreviewIcon'
import { FilterIcon, DollarSignIcon, CheckIcon, XSquareIcon, CheckSquareIcon, FolderPlusIcon, ListIcon, GridIcon, TrashIcon, UserPlusIcon, PlusIcon, CreditCardIcon } from 'vue-feather-icons'
import SortingIcon from '@/components/FilesView/Icons/SortingIcon'
export default {
name: 'MobileActionButton',
@@ -30,13 +31,14 @@
'icon'
],
components: {
SortingAndPreviewIcon,
SortingIcon,
CheckSquareIcon,
DollarSignIcon,
CreditCardIcon,
FolderPlusIcon,
UserPlusIcon,
XSquareIcon,
FilterIcon,
CheckIcon,
TrashIcon,
PlusIcon,
@@ -52,9 +54,9 @@
.mobile-action-button {
background: $light_background;
margin-right: 15px;
margin-right: 8px;
border-radius: 8px;
padding: 7px 10px;
padding: 7px 14px;
cursor: pointer;
border: none;
@include transition(150ms);
@@ -68,7 +70,7 @@
margin-right: 10px;
@include font-size(14);
path, line, polyline, rect, circle {
path, line, polyline, rect, circle, polygon {
@include transition(150ms);
}
}
@@ -89,7 +91,7 @@
.mobile-action-button {
background: $dark_mode_foreground;
path, line, polyline, rect, circle {
path, line, polyline, rect, circle, polygon {
color: inherit;
}

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