mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-05 18:23:48 +00:00
UI improvements part 2
This commit is contained in:
@@ -399,7 +399,7 @@ return [
|
||||
'global.total' => 'Total',
|
||||
'input_image.supported' => 'Supported formats are .png, .jpg, .jpeg.',
|
||||
'input_image.title' => 'Upload Image',
|
||||
'inputs.placeholder_search_files' => 'Search for anything...',
|
||||
'inputs.placeholder_search_files' => 'Search anything...',
|
||||
'item_thumbnail.deleted_at' => 'Deleted {time}',
|
||||
'item_thumbnail.original_location' => 'Original Location',
|
||||
'locations.home' => 'Files',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"/js/main.js": "/js/main.js",
|
||||
"/css/app.css": "/css/app.css",
|
||||
"/css/tailwind.css": "/css/tailwind.css",
|
||||
"/chunks/admin.js": "/chunks/admin.js?id=88821c570ece7a4835c8",
|
||||
"/chunks/admin.js": "/chunks/admin.js?id=de73ccab1ced122c79f9",
|
||||
"/chunks/admin-account.js": "/chunks/admin-account.js?id=6e28465565ea92af804f",
|
||||
"/chunks/admin-account~chunks/app-appearance~chunks/app-email~chunks/app-index~chunks/app-setup~chunks~ba362dfc.js": "/chunks/admin-account~chunks/app-appearance~chunks/app-email~chunks/app-index~chunks/app-setup~chunks~ba362dfc.js?id=f1db11992a10d86198ae",
|
||||
"/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~a2d1c36e.js": "/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~a2d1c36e.js?id=bbdda6115aa358c2209e",
|
||||
@@ -12,7 +12,7 @@
|
||||
"/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/settin~673d1ac3.js": "/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/settin~673d1ac3.js?id=34845d890e9e65d2adc0",
|
||||
"/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/settin~97130d1f.js": "/chunks/admin~chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/settin~97130d1f.js?id=8da02dcc87f434aca532",
|
||||
"/chunks/admin~chunks/platform~chunks/settings.js": "/chunks/admin~chunks/platform~chunks/settings.js?id=457420de4eafe9f1c5d3",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js?id=c7550917d07310acecff",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.js?id=d70888d9345ad027bff8",
|
||||
"/chunks/admin~chunks/platform~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/shared.js?id=3e732ede912619794ed9",
|
||||
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=f320fe6298f15a06d573",
|
||||
"/chunks/app-appearance~chunks/app-email~chunks/app-index~chunks/payments/billings~chunks/payments/set~0dc0a1dd.js": "/chunks/app-appearance~chunks/app-email~chunks/app-index~chunks/payments/billings~chunks/payments/set~0dc0a1dd.js?id=85c3dcde9e03e25b549e",
|
||||
@@ -39,7 +39,7 @@
|
||||
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=6c86916c6c6f679fa86b",
|
||||
"/chunks/email-verified.js": "/chunks/email-verified.js?id=fcba9acf60a855b730d5",
|
||||
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=037716aec84bcf2dbd87",
|
||||
"/chunks/files.js": "/chunks/files.js?id=692eff6c814b00ac7d97",
|
||||
"/chunks/files.js": "/chunks/files.js?id=34950cf3b0c8f604bf38",
|
||||
"/chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/shared~chunks/share~c7960950.js": "/chunks/files~chunks/my-shared-items~chunks/platform~chunks/recent-uploads~chunks/shared~chunks/share~c7960950.js?id=f41b30739fcbba3ae537",
|
||||
"/chunks/files~chunks/my-shared-items~chunks/recent-uploads~chunks/shared-with-me~chunks/shared/files~~34b5eb22.js": "/chunks/files~chunks/my-shared-items~chunks/recent-uploads~chunks/shared-with-me~chunks/shared/files~~34b5eb22.js?id=94ead73a2f7abcbc3214",
|
||||
"/chunks/files~chunks/my-shared-items~chunks/recent-uploads~chunks/shared-with-me~chunks/shared/files~~bf3ddedc.js": "/chunks/files~chunks/my-shared-items~chunks/recent-uploads~chunks/shared-with-me~chunks/shared/files~~bf3ddedc.js?id=6489d55d6d88986008c9",
|
||||
@@ -49,7 +49,7 @@
|
||||
"/chunks/installation-disclaimer.js": "/chunks/installation-disclaimer.js?id=a38af72f7ea45f34ffb9",
|
||||
"/chunks/invitation.js": "/chunks/invitation.js?id=ce0aa06dd9c62f505b9b",
|
||||
"/chunks/invoices.js": "/chunks/invoices.js?id=2a61a6196dc553fe193d",
|
||||
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=ef0a2dbe808eaee42c1f",
|
||||
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=782261b00546f4590849",
|
||||
"/chunks/not-found.js": "/chunks/not-found.js?id=bd6cc309172531900b13",
|
||||
"/chunks/page-edit.js": "/chunks/page-edit.js?id=5ff141bd6538ec84ecff",
|
||||
"/chunks/pages.js": "/chunks/pages.js?id=1ce97ecc061c94d203c3",
|
||||
@@ -69,16 +69,16 @@
|
||||
"/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js": "/chunks/platform~chunks/shared~chunks/shared-with-me~chunks/team-folders.js?id=66e964be4ab127b1f723",
|
||||
"/chunks/profile.js": "/chunks/profile.js?id=f86f4783c664ca19e6ed",
|
||||
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=d9af0efad2af2679954b",
|
||||
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=8577d4c771602671b38a",
|
||||
"/chunks/settings.js": "/chunks/settings.js?id=2bf24c09d7a7e4e311e3",
|
||||
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=376eafcf7e98317b5092",
|
||||
"/chunks/settings.js": "/chunks/settings.js?id=655804d5542f6c3907d5",
|
||||
"/chunks/settings-password.js": "/chunks/settings-password.js?id=5663c0b40d30395b1800",
|
||||
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=03dc91e6eca3401c7264",
|
||||
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=651d5accf401908724c5",
|
||||
"/chunks/shared.js": "/chunks/shared.js?id=a140c15b483547b020e9",
|
||||
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=e38098eca4e38683a83b",
|
||||
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=5ad15d8de528f9c45157",
|
||||
"/chunks/shared-with-me~chunks/team-folders.js": "/chunks/shared-with-me~chunks/team-folders.js?id=abf65131397ea2b12355",
|
||||
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=09f54f209289c79ccc33",
|
||||
"/chunks/shared/files.js": "/chunks/shared/files.js?id=84377b3190940b5196f6",
|
||||
"/chunks/shared/files.js": "/chunks/shared/files.js?id=d2b2314b1671457be48a",
|
||||
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=1abb5dd58d0ed626cd6e",
|
||||
"/chunks/sign-in.js": "/chunks/sign-in.js?id=e716349738364703249e",
|
||||
"/chunks/sign-up.js": "/chunks/sign-up.js?id=fedc03943b75d930b982",
|
||||
@@ -87,9 +87,9 @@
|
||||
"/chunks/subscription-plans.js": "/chunks/subscription-plans.js?id=15d40df6f0b187cf1129",
|
||||
"/chunks/subscription-service.js": "/chunks/subscription-service.js?id=3fffee3b8bab3e23ba18",
|
||||
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=d36f7ea9fc48b0226565",
|
||||
"/chunks/team-folders.js": "/chunks/team-folders.js?id=d0b1bb2f9e63fa36dd50",
|
||||
"/chunks/team-folders.js": "/chunks/team-folders.js?id=7ffd359b25ff016da5de",
|
||||
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=145f1b0766214eee1aad",
|
||||
"/chunks/trash.js": "/chunks/trash.js?id=1f5f349fb9ec23ba2e93",
|
||||
"/chunks/trash.js": "/chunks/trash.js?id=1a2baf87714da126f8f7",
|
||||
"/chunks/user.js": "/chunks/user.js?id=45f0a820b34424ad3fe9",
|
||||
"/chunks/user-create.js": "/chunks/user-create.js?id=ec5e0749e0fc93be4664",
|
||||
"/chunks/user-delete.js": "/chunks/user-delete.js?id=91cd831e23203fd3157c",
|
||||
@@ -347,5 +347,57 @@
|
||||
"/chunks/app-language.504629177b6761c98736.hot-update.js": "/chunks/app-language.504629177b6761c98736.hot-update.js",
|
||||
"/chunks/app-language.92a8a483adc8df63a01a.hot-update.js": "/chunks/app-language.92a8a483adc8df63a01a.hot-update.js",
|
||||
"/chunks/app-language.3d120b13bef15acb9090.hot-update.js": "/chunks/app-language.3d120b13bef15acb9090.hot-update.js",
|
||||
"/chunks/app-language.460ec4352b584c67a6d4.hot-update.js": "/chunks/app-language.460ec4352b584c67a6d4.hot-update.js"
|
||||
"/chunks/app-language.460ec4352b584c67a6d4.hot-update.js": "/chunks/app-language.460ec4352b584c67a6d4.hot-update.js",
|
||||
"/chunks/admin.aea3f37f694b0ed59df9.hot-update.js": "/chunks/admin.aea3f37f694b0ed59df9.hot-update.js",
|
||||
"/chunks/admin.9eca60f21105b10f5ba1.hot-update.js": "/chunks/admin.9eca60f21105b10f5ba1.hot-update.js",
|
||||
"/chunks/settings.2a86b6bb32721c26847c.hot-update.js": "/chunks/settings.2a86b6bb32721c26847c.hot-update.js",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.64bc74803ac686236844.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.64bc74803ac686236844.hot-update.js",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.8bf61f46a1f5c14faf93.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.8bf61f46a1f5c14faf93.hot-update.js",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.1e15dbc93d093e24e1d7.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.1e15dbc93d093e24e1d7.hot-update.js",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.0032e84bf50c332eb847.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.0032e84bf50c332eb847.hot-update.js",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.78b3544dab4173fc8a42.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.78b3544dab4173fc8a42.hot-update.js",
|
||||
"/chunks/admin~chunks/platform~chunks/settings~chunks/shared.e6b8c42db873cdfe2ccd.hot-update.js": "/chunks/admin~chunks/platform~chunks/settings~chunks/shared.e6b8c42db873cdfe2ccd.hot-update.js",
|
||||
"/chunks/files.94851e6c657d1b2f870c.hot-update.js": "/chunks/files.94851e6c657d1b2f870c.hot-update.js",
|
||||
"/chunks/files.bcb4fdd736c68a303dce.hot-update.js": "/chunks/files.bcb4fdd736c68a303dce.hot-update.js",
|
||||
"/chunks/files.58b89e95a2b88f8cb7d6.hot-update.js": "/chunks/files.58b89e95a2b88f8cb7d6.hot-update.js",
|
||||
"/chunks/files.95859042c75e5ae784b1.hot-update.js": "/chunks/files.95859042c75e5ae784b1.hot-update.js",
|
||||
"/chunks/files.0ba73302a3f70289643d.hot-update.js": "/chunks/files.0ba73302a3f70289643d.hot-update.js",
|
||||
"/chunks/files.a5af19f6febc9566408d.hot-update.js": "/chunks/files.a5af19f6febc9566408d.hot-update.js",
|
||||
"/js/main.062b8801a3a56279b3e7.hot-update.js": "/js/main.062b8801a3a56279b3e7.hot-update.js",
|
||||
"/js/main.8b87da76ecc0a343f903.hot-update.js": "/js/main.8b87da76ecc0a343f903.hot-update.js",
|
||||
"/js/main.61df756dc6cbc8f7f986.hot-update.js": "/js/main.61df756dc6cbc8f7f986.hot-update.js",
|
||||
"/js/main.c72ce546879c4e65b027.hot-update.js": "/js/main.c72ce546879c4e65b027.hot-update.js",
|
||||
"/js/main.b0160643fa00ebdfd1b0.hot-update.js": "/js/main.b0160643fa00ebdfd1b0.hot-update.js",
|
||||
"/js/main.1fb5fe7522cbb5e2d7c9.hot-update.js": "/js/main.1fb5fe7522cbb5e2d7c9.hot-update.js",
|
||||
"/js/main.230eb66a5d86dbc0ed27.hot-update.js": "/js/main.230eb66a5d86dbc0ed27.hot-update.js",
|
||||
"/js/main.2a9d2199a4d1929950c8.hot-update.js": "/js/main.2a9d2199a4d1929950c8.hot-update.js",
|
||||
"/js/main.7fd60acd3a251219469b.hot-update.js": "/js/main.7fd60acd3a251219469b.hot-update.js",
|
||||
"/js/main.8d856d552f4be72be0e3.hot-update.js": "/js/main.8d856d552f4be72be0e3.hot-update.js",
|
||||
"/js/main.2511dc93f991ae56e07b.hot-update.js": "/js/main.2511dc93f991ae56e07b.hot-update.js",
|
||||
"/js/main.c5c372824b2d33da7e09.hot-update.js": "/js/main.c5c372824b2d33da7e09.hot-update.js",
|
||||
"/js/main.ccf5a2288497238447c3.hot-update.js": "/js/main.ccf5a2288497238447c3.hot-update.js",
|
||||
"/js/main.f90c4343d2960e75b4a8.hot-update.js": "/js/main.f90c4343d2960e75b4a8.hot-update.js",
|
||||
"/chunks/files.813fa4d730b4dc32cf36.hot-update.js": "/chunks/files.813fa4d730b4dc32cf36.hot-update.js",
|
||||
"/chunks/my-shared-items.db4e67466ef9527ef443.hot-update.js": "/chunks/my-shared-items.db4e67466ef9527ef443.hot-update.js",
|
||||
"/chunks/recent-uploads.db4e67466ef9527ef443.hot-update.js": "/chunks/recent-uploads.db4e67466ef9527ef443.hot-update.js",
|
||||
"/chunks/shared-with-me.db4e67466ef9527ef443.hot-update.js": "/chunks/shared-with-me.db4e67466ef9527ef443.hot-update.js",
|
||||
"/chunks/shared/files.db4e67466ef9527ef443.hot-update.js": "/chunks/shared/files.db4e67466ef9527ef443.hot-update.js",
|
||||
"/chunks/team-folders.db4e67466ef9527ef443.hot-update.js": "/chunks/team-folders.db4e67466ef9527ef443.hot-update.js",
|
||||
"/chunks/trash.db4e67466ef9527ef443.hot-update.js": "/chunks/trash.db4e67466ef9527ef443.hot-update.js",
|
||||
"/js/main.40e0f100d21dfca78290.hot-update.js": "/js/main.40e0f100d21dfca78290.hot-update.js",
|
||||
"/js/main.5df103d6e3a7028d60f5.hot-update.js": "/js/main.5df103d6e3a7028d60f5.hot-update.js",
|
||||
"/js/main.2edd1c2f16d9ad1ff905.hot-update.js": "/js/main.2edd1c2f16d9ad1ff905.hot-update.js",
|
||||
"/js/main.a2b467f55f6d2a7f08c3.hot-update.js": "/js/main.a2b467f55f6d2a7f08c3.hot-update.js",
|
||||
"/js/main.4fda0a2e7a0871a74a1c.hot-update.js": "/js/main.4fda0a2e7a0871a74a1c.hot-update.js",
|
||||
"/js/main.58ebab9fd52ad6e4dd61.hot-update.js": "/js/main.58ebab9fd52ad6e4dd61.hot-update.js",
|
||||
"/js/main.219e0bfac030c6eceaf3.hot-update.js": "/js/main.219e0bfac030c6eceaf3.hot-update.js",
|
||||
"/js/main.631f4fd4e5ae2ec555c6.hot-update.js": "/js/main.631f4fd4e5ae2ec555c6.hot-update.js",
|
||||
"/js/main.cee4ccc7d8c4e4c5e8a8.hot-update.js": "/js/main.cee4ccc7d8c4e4c5e8a8.hot-update.js",
|
||||
"/js/main.e33e24f9ce88070ae233.hot-update.js": "/js/main.e33e24f9ce88070ae233.hot-update.js",
|
||||
"/js/main.c61b27f8bdd2027891be.hot-update.js": "/js/main.c61b27f8bdd2027891be.hot-update.js",
|
||||
"/js/main.19a5a11f2f40dcc50f6d.hot-update.js": "/js/main.19a5a11f2f40dcc50f6d.hot-update.js",
|
||||
"/js/main.c0c79fc6ab3ea3113995.hot-update.js": "/js/main.c0c79fc6ab3ea3113995.hot-update.js",
|
||||
"/js/main.866acfdd88418791a158.hot-update.js": "/js/main.866acfdd88418791a158.hot-update.js",
|
||||
"/js/main.a6730a78442e26530fba.hot-update.js": "/js/main.a6730a78442e26530fba.hot-update.js",
|
||||
"/js/main.f7c7fe63fce4501b3c61.hot-update.js": "/js/main.f7c7fe63fce4501b3c61.hot-update.js"
|
||||
}
|
||||
|
||||
@@ -76,7 +76,8 @@
|
||||
<div v-if="actions.length !== 0" class="mb-2">
|
||||
<div v-for="(result, i) in actions" :key="result.action.value" class="relative">
|
||||
<div
|
||||
class="flex items-center px-3.5 py-2.5"
|
||||
@mousedown="openAction(result)"
|
||||
class="flex items-center px-3.5 py-2.5 cursor-pointer"
|
||||
:class="{'dark:bg-4x-dark-foreground bg-light-background rounded-xl': i === index}"
|
||||
>
|
||||
<settings-icon v-if="['AppOthers', 'Profile', 'Password'].includes(result.action.value)" size="18" class="vue-feather text-theme"/>
|
||||
|
||||
21
resources/js/helpers/itemHelpers.js
vendored
21
resources/js/helpers/itemHelpers.js
vendored
@@ -36,7 +36,7 @@ const itemHelpers = {
|
||||
})
|
||||
}
|
||||
|
||||
Vue.prototype.$downloadSelection = function (item) {
|
||||
Vue.prototype.$downloadSelection = function (item = undefined) {
|
||||
// Show alert message when download is disabled
|
||||
if (! store.getters.user.data.meta.restrictions.canDownload) {
|
||||
Vue.prototype.$temporarilyDisabledDownload()
|
||||
@@ -44,12 +44,25 @@ const itemHelpers = {
|
||||
return
|
||||
}
|
||||
|
||||
// Download folder zip
|
||||
if (item && item.data.type === 'folder') {
|
||||
store.dispatch('downloadZip', item)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Download single item
|
||||
if (item && item.data.type !== 'folder') {
|
||||
Vue.prototype.$downloadFile(item.data.attributes.file_url, item.data.attributes.name + '.' + item.data.attributes.mimetype)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Download selection
|
||||
let clipboard = store.getters.clipboard
|
||||
|
||||
if (clipboard.length > 1 || (clipboard.length === 1 && clipboard[0].data.type === 'folder'))
|
||||
if (clipboard.length > 1 || (clipboard.length === 1 && clipboard[0].data.type === 'folder')) {
|
||||
store.dispatch('downloadZip')
|
||||
else {
|
||||
Vue.prototype.$downloadFile(item.data.attributes.file_url, item.data.attributes.name + '.' + item.data.attributes.mimetype)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
28
resources/js/store/modules/fileFunctions.js
vendored
28
resources/js/store/modules/fileFunctions.js
vendored
@@ -14,25 +14,31 @@ const defaultState = {
|
||||
}
|
||||
|
||||
const actions = {
|
||||
downloadZip: ({getters}) => {
|
||||
downloadZip: ({getters}, item = undefined) => {
|
||||
let files = []
|
||||
|
||||
// get ids of selected files
|
||||
getters.clipboard.forEach(file => {
|
||||
let type = file.data.type === 'folder'
|
||||
? 'folder'
|
||||
: 'file'
|
||||
// Get if from retrieved item
|
||||
if (item) {
|
||||
files.push(item.data.id + '|folder')
|
||||
}
|
||||
|
||||
files.push(file.data.id + '|' + type)
|
||||
})
|
||||
// Get ids of selected files
|
||||
if (! item) {
|
||||
getters.clipboard.forEach(file => {
|
||||
let type = file.data.type === 'folder'
|
||||
? 'folder'
|
||||
: 'file'
|
||||
|
||||
let items = files.join(',')
|
||||
files.push(file.data.id + '|' + type)
|
||||
})
|
||||
}
|
||||
|
||||
// Get route
|
||||
let route = getters.sharedDetail
|
||||
? `/api/zip/${router.currentRoute.params.token}?items=${items}`
|
||||
: `/api/zip?items=${items}`
|
||||
? `/api/zip/${router.currentRoute.params.token}?items=${files.join(',')}`
|
||||
: `/api/zip?items=${files.join(',')}`
|
||||
|
||||
// Download zip
|
||||
Vue.prototype.$downloadFile(route, 'files.zip')
|
||||
},
|
||||
moveItem: ({commit, getters, dispatch}, {to_item, noSelectedItem}) => {
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
</ContentGroup>
|
||||
</ContentSidebar>
|
||||
|
||||
<router-view class="md:px-6 px-2.5 w-full overflow-x-hidden relative lg:pt-6" />
|
||||
<router-view class="lg:pt-6 md:px-6 px-2.5 lg:pb-0 pb-12 w-full overflow-x-hidden relative" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
|
||||
</OptionGroup>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
|
||||
</OptionGroup>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
|
||||
</OptionGroup>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
|
||||
</OptionGroup>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
|
||||
</OptionGroup>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
|
||||
</OptionGroup>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<Option @click.native="$emptyTrash" :title="$t('context_menu.empty_trash')" icon="empty-trash" />
|
||||
</OptionGroup>
|
||||
<OptionGroup>
|
||||
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
|
||||
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
|
||||
</OptionGroup>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<MobileNavigationToolbar />
|
||||
|
||||
<div v-if="user" class="md:px-6 px-2.5 w-full overflow-x-hidden relative lg:pt-6 xl:max-w-screen-lg md:max-w-4xl mx-auto">
|
||||
<div v-if="user" class="lg:pt-6 md:px-6 px-2.5 lg:pb-0 pb-12 w-full overflow-x-hidden relative xl:max-w-screen-lg md:max-w-4xl mx-auto">
|
||||
<div v-if="! isLoading" id="page-content">
|
||||
|
||||
<div class="card shadow-card sticky top-0 z-10" style="padding-bottom: 0">
|
||||
|
||||
@@ -11,15 +11,15 @@ use Domain\Admin\Controllers\Dashboard\GetNewbiesController;
|
||||
use Domain\Admin\Controllers\Users\ChangeUserRoleController;
|
||||
use Domain\Settings\Controllers\UpdateSettingValueController;
|
||||
use Domain\Admin\Controllers\Users\ResetUserPasswordController;
|
||||
use Domain\Transactions\Controllers\GetAllTransactionsController;
|
||||
use Domain\Admin\Controllers\Dashboard\GetDashboardDataController;
|
||||
use Domain\Transactions\Controllers\GetUserTransactionsController;
|
||||
use Domain\Localization\Controllers\UpdateLanguageStringController;
|
||||
use Domain\Admin\Controllers\Users\ShowUserStorageCapacityController;
|
||||
use Domain\Admin\Controllers\Dashboard\GetLatestTransactionsController;
|
||||
use Domain\Admin\Controllers\Users\ChangeUserStorageCapacityController;
|
||||
use Domain\Settings\Controllers\StoreSocialServiceCredentialsController;
|
||||
use Domain\Settings\Controllers\StorePaymentServiceCredentialsController;
|
||||
use Domain\Transactions\Controllers\GetAllTransactionsController;
|
||||
use Domain\Transactions\Controllers\GetUserTransactionsController;
|
||||
|
||||
// Dashboard
|
||||
Route::group(['prefix' => 'dashboard'], function () {
|
||||
|
||||
@@ -38,7 +38,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
Gate::define($ability, function (?User $user, File | Folder $item, ?Share $share) use ($ability) {
|
||||
// If share link exist, then check share access
|
||||
if ($share) {
|
||||
return $this->share_guard($share, $item);
|
||||
return $this->shareGuard($share, $item);
|
||||
}
|
||||
|
||||
// Check user owner status
|
||||
@@ -47,7 +47,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
}
|
||||
|
||||
// Check team member ability to access into requested item
|
||||
return $this->team_member_guard($item, $user, $ability);
|
||||
return $this->teamMemberGuard($item, $user, $ability);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -58,9 +58,9 @@ class AuthServiceProvider extends ServiceProvider
|
||||
});
|
||||
}
|
||||
|
||||
private function share_guard(Share $share, Folder | File $item): bool
|
||||
private function shareGuard(Share $share, Folder | File $item): bool
|
||||
{
|
||||
if (! $share->is_protected && $share->user_id === $item->user_id) {
|
||||
if (! $share->is_protected) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
return $share->user_id === $item->user_id;
|
||||
}
|
||||
|
||||
private function team_member_guard(Folder | File $item, ?User $user, $ability): bool
|
||||
private function teamMemberGuard(Folder | File $item, ?User $user, $ability): bool
|
||||
{
|
||||
$teamFolder = $item->getLatestParent();
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace App\Users\Requests;
|
||||
use App\Users\Rules\EmailProvider;
|
||||
use App\Users\Rules\ReCaptchaRules;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use App\Users\Rules\PasswordValidationRules;
|
||||
use Illuminate\Validation\Rules\RequiredIf;
|
||||
use App\Users\Rules\PasswordValidationRules;
|
||||
|
||||
class RegisterUserRequest extends FormRequest
|
||||
{
|
||||
@@ -29,10 +29,10 @@ class RegisterUserRequest extends FormRequest
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email', new EmailProvider],
|
||||
'name' => 'required|string|max:255',
|
||||
'password' => $this->passwordRules(),
|
||||
'reCaptcha' => [new RequiredIf(get_settings('allowed_recaptcha') == 1), 'string', app(ReCaptchaRules::class)]
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email', new EmailProvider],
|
||||
'name' => 'required|string|max:255',
|
||||
'password' => $this->passwordRules(),
|
||||
'reCaptcha' => [new RequiredIf(get_settings('allowed_recaptcha') == 1), 'string', app(ReCaptchaRules::class)],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Users\Rules;
|
||||
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
@@ -17,16 +16,17 @@ class ReCaptchaRules implements Rule
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
$client = new Client();
|
||||
$response = $client->post('https://www.google.com/recaptcha/api/siteverify',
|
||||
$response = $client->post(
|
||||
'https://www.google.com/recaptcha/api/siteverify',
|
||||
[
|
||||
'form_params' => [
|
||||
'secret' => env('RECAPTCHA_CLIENT_SECRET', false),
|
||||
'secret' => env('RECAPTCHA_CLIENT_SECRET', false),
|
||||
'remoteip' => request()->getClientIp(),
|
||||
'response' => $value
|
||||
]
|
||||
'response' => $value,
|
||||
],
|
||||
]
|
||||
);
|
||||
$body = json_decode((string)$response->getBody());
|
||||
$body = json_decode((string) $response->getBody());
|
||||
|
||||
return $body->success;
|
||||
}
|
||||
@@ -35,4 +35,4 @@ class ReCaptchaRules implements Rule
|
||||
{
|
||||
return 'Are you a robot?';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Files\Actions;
|
||||
|
||||
use Domain\Folders\Models\Folder;
|
||||
|
||||
@@ -25,9 +25,9 @@ class SendContactMessageRequest extends FormRequest
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email',
|
||||
'message' => 'required|string',
|
||||
'reCaptcha' => [new RequiredIf(get_settings('allowed_recaptcha') == 1), 'string', app(ReCaptchaRules::class)]
|
||||
'email' => 'required|email',
|
||||
'message' => 'required|string',
|
||||
'reCaptcha' => [new RequiredIf(get_settings('allowed_recaptcha') == 1), 'string', app(ReCaptchaRules::class)],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class StoreSocialServiceCredentialsController
|
||||
if (! app()->runningUnitTests()) {
|
||||
$credentials = [
|
||||
'facebook' => [
|
||||
'FACEBOOK_CLIENT_ID' => $request->input('client_id'),
|
||||
'FACEBOOK_CLIENT_ID' => $request->input('client_id'),
|
||||
'FACEBOOK_CLIENT_SECRET' => $request->input('client_secret'),
|
||||
],
|
||||
'google' => [
|
||||
@@ -42,7 +42,6 @@ class StoreSocialServiceCredentialsController
|
||||
'RECAPTCHA_CLIENT_ID' => $request->input('client_id'),
|
||||
'RECAPTCHA_CLIENT_SECRET' => $request->input('client_secret'),
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
// Store credentials into the .env file
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace Domain\Transactions\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Users\Models\User;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Transactions\Resources\TransactionCollection;
|
||||
|
||||
class GetUserTransactionsController extends Controller
|
||||
|
||||
@@ -6,9 +6,8 @@ use Domain\Folders\Models\Folder;
|
||||
|
||||
class GetItemsListFromUrlParamAction
|
||||
{
|
||||
public function __invoke(
|
||||
string $user_id
|
||||
): array {
|
||||
public function __invoke(): array
|
||||
{
|
||||
$list = explode(',', request()->get('items'));
|
||||
|
||||
$itemList = collect($list)
|
||||
@@ -29,12 +28,10 @@ class GetItemsListFromUrlParamAction
|
||||
->where('type', 'file')
|
||||
->pluck('id');
|
||||
|
||||
$folders = Folder::whereUserId($user_id)
|
||||
->whereIn('id', $folderIds)
|
||||
$folders = Folder::whereIn('id', $folderIds)
|
||||
->get();
|
||||
|
||||
$files = File::whereUserId($user_id)
|
||||
->whereIn('id', $fileIds)
|
||||
$files = File::whereIn('id', $fileIds)
|
||||
->get();
|
||||
|
||||
return [$folders, $files];
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?php
|
||||
namespace Domain\Zip\Actions;
|
||||
|
||||
use Gate;
|
||||
use ZipStream\ZipStream;
|
||||
use Illuminate\Support\Str;
|
||||
use Domain\Sharing\Models\Share;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use STS\ZipStream\ZipStreamFacade as Zip;
|
||||
|
||||
@@ -17,9 +17,6 @@ class ZipAction
|
||||
Collection $files,
|
||||
?Share $shared = null
|
||||
): ZipStream {
|
||||
// Get user id
|
||||
$user_id = Auth::id() ?? $shared->user_id;
|
||||
|
||||
// Get zip name from single requested folder
|
||||
if ($files->isEmpty() && $folders->count() === 1) {
|
||||
$zipName = Str::slug($folders->first()->name) . '.zip';
|
||||
@@ -29,7 +26,12 @@ class ZipAction
|
||||
$zip = Zip::create($zipName ?? 'files.zip');
|
||||
|
||||
// Zip Files
|
||||
$files->map(function ($file) use ($zip) {
|
||||
$files->map(function ($file) use ($zip, $shared) {
|
||||
// Check user privileges to the file
|
||||
if (! Gate::any(['can-edit', 'can-view'], [$file, $shared])) {
|
||||
abort(403, 'Access Denied');
|
||||
}
|
||||
|
||||
// get file path
|
||||
$filePath = "files/$file->user_id/$file->basename";
|
||||
|
||||
@@ -50,11 +52,15 @@ class ZipAction
|
||||
});
|
||||
|
||||
// Zip Folders
|
||||
$folders->map(function ($folder) use ($zip, $user_id) {
|
||||
$folders->map(function ($folder) use ($zip, $shared) {
|
||||
// Check user privileges to the folder
|
||||
if (! Gate::any(['can-edit', 'can-view'], [$folder, $shared])) {
|
||||
abort(403, 'Access Denied');
|
||||
}
|
||||
|
||||
// Get folder
|
||||
$requested_folder = Folder::with(['folders.files', 'files'])
|
||||
->where('id', $folder->id)
|
||||
->where('user_id', $user_id)
|
||||
->with('folders')
|
||||
->first();
|
||||
|
||||
@@ -62,7 +68,7 @@ class ZipAction
|
||||
|
||||
foreach ($folderFiles as $file) {
|
||||
// get file path
|
||||
$filePath = "files/$user_id/{$file['basename']}";
|
||||
$filePath = "files/{$file['user_id']}/{$file['basename']}";
|
||||
|
||||
// Add file into zip
|
||||
if (Storage::exists($filePath)) {
|
||||
|
||||
@@ -27,10 +27,7 @@ class VisitorZipController extends Controller
|
||||
Request $request,
|
||||
Share $shared,
|
||||
): ZipStream {
|
||||
// Check ability to access protected share record
|
||||
($this->protectShareRecord)($shared);
|
||||
|
||||
list($folders, $files) = ($this->getItemsListFromUrlParam)($shared->user_id);
|
||||
list($folders, $files) = ($this->getItemsListFromUrlParam)();
|
||||
|
||||
// Check access to requested folders
|
||||
if ($folders->isNotEmpty()) {
|
||||
|
||||
@@ -21,7 +21,7 @@ class ZipController extends Controller
|
||||
Request $request,
|
||||
): ZipStream {
|
||||
// Get list of folders and files from requested url parameter
|
||||
list($folders, $files) = ($this->getItemsListFromUrlParam)(auth()->id());
|
||||
list($folders, $files) = ($this->getItemsListFromUrlParam)();
|
||||
|
||||
// Zip items
|
||||
$zip = ($this->zip)($folders, $files);
|
||||
|
||||
@@ -913,13 +913,8 @@ if (! function_exists('remove_accents')) {
|
||||
if (! function_exists('get_files_for_zip')) {
|
||||
/**
|
||||
* Get all files from folder and get their folder location in VueFileManager directories
|
||||
*
|
||||
* @param $folders
|
||||
* @param null $files
|
||||
* @param array $path
|
||||
* @return array
|
||||
*/
|
||||
function get_files_for_zip($folders, $files, $path = [])
|
||||
function get_files_for_zip($folders, $files, array $path = []): array
|
||||
{
|
||||
// Return file list
|
||||
if (! isset($folders->folders)) {
|
||||
@@ -933,6 +928,7 @@ if (! function_exists('get_files_for_zip')) {
|
||||
$folders->files->each(function ($file) use ($files, $path) {
|
||||
$files->push([
|
||||
'name' => $file->name,
|
||||
'user_id' => $file->user_id,
|
||||
'basename' => $file->basename,
|
||||
'mimetype' => $file->mimetype,
|
||||
'folder_path' => implode('/', $path),
|
||||
|
||||
@@ -335,7 +335,6 @@ class SignFlowTest extends TestCase
|
||||
*/
|
||||
public function it_create_user_from_register_form_with_reCaptcha()
|
||||
{
|
||||
|
||||
Setting::updateOrCreate([
|
||||
'name' => 'allowed_recaptcha',
|
||||
], [
|
||||
@@ -351,7 +350,7 @@ class SignFlowTest extends TestCase
|
||||
'password' => 'SecretPassword',
|
||||
'password_confirmation' => 'SecretPassword',
|
||||
'name' => 'John Doe',
|
||||
'reCaptcha' => 'fakeToken'
|
||||
'reCaptcha' => 'fakeToken',
|
||||
])->assertStatus(201);
|
||||
|
||||
$this
|
||||
|
||||
@@ -174,7 +174,7 @@ class SettingsTest extends TestCase
|
||||
])->assertStatus(204);
|
||||
|
||||
$this->assertDatabaseHas('settings', [
|
||||
'name' => 'allowed_facebook_login',
|
||||
'name' => 'allowed_facebook',
|
||||
'value' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
110
tests/Domain/Teams/TeamFileAccessTest.php
Normal file
110
tests/Domain/Teams/TeamFileAccessTest.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
namespace Tests\Domain\Teams;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Users\Models\User;
|
||||
use Domain\Files\Models\File;
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Domain\Teams\Models\TeamFolderMember;
|
||||
|
||||
class TeamFileAccessTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function team_member_download_folder_as_zip()
|
||||
{
|
||||
$user = User::factory()
|
||||
->hasSettings()
|
||||
->create();
|
||||
|
||||
$folder = Folder::factory(Folder::class)
|
||||
->create([
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
|
||||
collect([0, 1])
|
||||
->each(function ($index) use ($folder, $user) {
|
||||
$file = UploadedFile::fake()
|
||||
->create("fake-file-$index.pdf", 1200, 'application/pdf');
|
||||
|
||||
$this
|
||||
->actingAs($user)
|
||||
->postJson('/api/upload', [
|
||||
'filename' => $file->name,
|
||||
'file' => $file,
|
||||
'parent_id' => $folder->id,
|
||||
'path' => '/' . $file->name,
|
||||
'is_last' => 'true',
|
||||
])->assertStatus(201);
|
||||
});
|
||||
|
||||
$member = User::factory()
|
||||
->hasSettings()
|
||||
->create();
|
||||
|
||||
// Attach user into members
|
||||
TeamFolderMember::create([
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $member->id,
|
||||
'permission' => 'can-edit',
|
||||
]);
|
||||
|
||||
$this
|
||||
->actingAs($member)
|
||||
->getJson("/api/zip?items=$folder->id|folder")
|
||||
->assertStatus(200)
|
||||
->assertHeader('content-type', 'application/x-zip');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function team_member_download_files_as_zip()
|
||||
{
|
||||
$user = User::factory()
|
||||
->hasSettings()
|
||||
->create();
|
||||
|
||||
$folder = Folder::factory(Folder::class)
|
||||
->create([
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
|
||||
collect([0, 1])
|
||||
->each(function ($index) use ($folder, $user) {
|
||||
$file = UploadedFile::fake()
|
||||
->create("fake-file-$index.pdf", 1200, 'application/pdf');
|
||||
|
||||
$this
|
||||
->actingAs($user)
|
||||
->postJson('/api/upload', [
|
||||
'filename' => $file->name,
|
||||
'file' => $file,
|
||||
'parent_id' => $folder->id,
|
||||
'path' => '/' . $file->name,
|
||||
'is_last' => 'true',
|
||||
])->assertStatus(201);
|
||||
});
|
||||
|
||||
$member = User::factory()
|
||||
->hasSettings()
|
||||
->create();
|
||||
|
||||
// Attach user into members
|
||||
TeamFolderMember::create([
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $member->id,
|
||||
'permission' => 'can-edit',
|
||||
]);
|
||||
|
||||
$files = File::all();
|
||||
|
||||
$this
|
||||
->actingAs($member)
|
||||
->getJson("/api/zip?items={$files->first()->id}|file,{$files->last()->id}|file")
|
||||
->assertStatus(200)
|
||||
->assertHeader('content-type', 'application/x-zip');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user