mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-18 08:12:15 +00:00
Shared link expiration backend
Redirect from sign in page when user is logged Updated README.md
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="action-button">
|
||||
<FontAwesomeIcon class="icon" :icon="icon" />
|
||||
<x-icon size="12" class="icon" v-if="icon === 'x'"></x-icon>
|
||||
<edit-2-icon size="12" class="icon" v-if="icon === 'pencil-alt'"></edit-2-icon>
|
||||
<span class="label">
|
||||
<slot></slot>
|
||||
</span>
|
||||
@@ -8,9 +9,15 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Edit2Icon, XIcon } from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'ActionButton',
|
||||
props: ['icon'],
|
||||
components: {
|
||||
Edit2Icon,
|
||||
XIcon,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -23,18 +30,17 @@
|
||||
|
||||
.label {
|
||||
@include font-size(12);
|
||||
color: $theme;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@include font-size(10);
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
margin-right: 2px;
|
||||
|
||||
path {
|
||||
fill: $theme;
|
||||
path, circle, line {
|
||||
stroke: $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="select-box">
|
||||
<div class="box-item"
|
||||
:class="{'selected': item.value === value}"
|
||||
:class="{'selected': item.value === input}"
|
||||
@click="getSelectedValue(item)"
|
||||
v-for="(item, i) in data" :key="i"
|
||||
>
|
||||
@@ -13,21 +13,28 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'SelectBoxInput',
|
||||
props: ['data'],
|
||||
props: [
|
||||
'data',
|
||||
'value',
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
value: undefined,
|
||||
input: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getSelectedValue(item) {
|
||||
if (! this.value || this.value !== item.value)
|
||||
this.value = item.value
|
||||
if (! this.input || this.input !== item.value)
|
||||
this.input = item.value
|
||||
else
|
||||
this.value = undefined
|
||||
this.input = undefined
|
||||
|
||||
this.$emit('input', this.value)
|
||||
this.$emit('input', this.input)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.value)
|
||||
this.input = this.value
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -41,14 +48,21 @@
|
||||
.select-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.box-item {
|
||||
padding: 12px 14px;
|
||||
margin-bottom: 10px;
|
||||
padding: 12px 4px;
|
||||
text-align: center;
|
||||
background: $light_background;
|
||||
border-radius: 8px;
|
||||
font-weight: 700;
|
||||
border: 2px solid $light_background;
|
||||
cursor: pointer;
|
||||
flex-direction: column;
|
||||
flex-basis: 55px;
|
||||
|
||||
.box-value {
|
||||
@include font-size(15);
|
||||
@@ -65,6 +79,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
.select-box {
|
||||
|
||||
.box-item {
|
||||
flex-basis: calc(34% - 10px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
|
||||
@@ -33,11 +33,17 @@
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
|
||||
<!--Set expiration-->
|
||||
<div class="input-wrapper">
|
||||
<label class="input-label">{{ $t('shared_form.label_expiration') }}:</label>
|
||||
<SelectBoxInput v-model="shareOptions.expiration" :data="expirationList" class="box"/>
|
||||
<!--More options-->
|
||||
<div class="more-options" v-if="isMoreOptions">
|
||||
|
||||
<!--Set expiration-->
|
||||
<div class="input-wrapper">
|
||||
<label class="input-label">{{ $t('shared_form.label_expiration') }}:</label>
|
||||
<SelectBoxInput v-model="shareOptions.expiration" :data="expirationList" class="box"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionButton @click.native="moreOptions" :icon="isMoreOptions ? 'x' : 'pencil-alt'">{{ moreOptionsTitle }}</ActionButton>
|
||||
</ValidationObserver>
|
||||
|
||||
<!--Copy generated link-->
|
||||
@@ -80,6 +86,7 @@
|
||||
import SwitchInput from '@/components/Others/Forms/SwitchInput'
|
||||
import SelectInput from '@/components/Others/Forms/SelectInput'
|
||||
import ThumbnailItem from '@/components/Others/ThumbnailItem'
|
||||
import ActionButton from '@/components/Others/ActionButton'
|
||||
import CopyInput from '@/components/Others/Forms/CopyInput'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
@@ -94,6 +101,7 @@
|
||||
ValidationObserver,
|
||||
SelectBoxInput,
|
||||
ThumbnailItem,
|
||||
ActionButton,
|
||||
PopupWrapper,
|
||||
PopupActions,
|
||||
PopupContent,
|
||||
@@ -105,7 +113,10 @@
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permissionOptions']),
|
||||
...mapGetters([
|
||||
'permissionOptions',
|
||||
'expirationList',
|
||||
]),
|
||||
itemTypeTitle() {
|
||||
return this.pickedItem && this.pickedItem.type === 'folder' ? this.$t('types.folder') : this.$t('types.file')
|
||||
},
|
||||
@@ -114,40 +125,13 @@
|
||||
},
|
||||
submitButtonText() {
|
||||
return this.isGeneratedShared ? this.$t('shared_form.button_done') : this.$t('shared_form.button_generate')
|
||||
},
|
||||
moreOptionsTitle() {
|
||||
return this.isMoreOptions ? this.$t('shared_form.button_close_options') : this.$t('shared_form.button_more_options')
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expirationList: [
|
||||
{
|
||||
label: this.$t('shared_form.expiration_hour', {value: 1}),
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: this.$t('shared_form.expiration_hour', {value: 2}),
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
label: this.$t('shared_form.expiration_hour', {value: 6}),
|
||||
value: '6',
|
||||
},
|
||||
{
|
||||
label: this.$t('shared_form.expiration_hour', {value: 12}),
|
||||
value: '12',
|
||||
},
|
||||
{
|
||||
label: this.$t('shared_form.expiration_day', {value: 1}),
|
||||
value: '24',
|
||||
},
|
||||
{
|
||||
label: this.$t('shared_form.expiration_day', {value: 2}),
|
||||
value: '48',
|
||||
},
|
||||
{
|
||||
label: this.$t('shared_form.expiration_day', {value: 7}),
|
||||
value: '168',
|
||||
},
|
||||
],
|
||||
shareOptions: {
|
||||
isPassword: false,
|
||||
expiration: undefined,
|
||||
@@ -160,9 +144,16 @@
|
||||
shareLink: undefined,
|
||||
isGeneratedShared: false,
|
||||
isLoading: false,
|
||||
isMoreOptions: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
moreOptions() {
|
||||
this.isMoreOptions = ! this.isMoreOptions
|
||||
|
||||
if (! this.isMoreOptions)
|
||||
this.shareOptions.expiration = undefined
|
||||
},
|
||||
async submitShareOptions() {
|
||||
|
||||
// If shared was generated, then close popup
|
||||
@@ -224,10 +215,12 @@
|
||||
permission: undefined,
|
||||
password: undefined,
|
||||
isPassword: false,
|
||||
expiration: undefined,
|
||||
type: undefined,
|
||||
unique_id: undefined,
|
||||
}
|
||||
this.isGeneratedShared = false
|
||||
this.isMoreOptions = false
|
||||
this.shareLink = undefined
|
||||
}, 150)
|
||||
})
|
||||
@@ -239,6 +232,10 @@
|
||||
@import "@assets/vue-file-manager/_inapp-forms.scss";
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.more-options {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
|
||||
&.password {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<label class="input-label">{{ $t('shared_form.label_password_protection') }}:</label>
|
||||
<SwitchInput v-model="shareOptions.isProtected" :state="shareOptions.isProtected" class="switch"/>
|
||||
</div>
|
||||
<ActionButton v-if="(pickedItem.shared.protected && canChangePassword) && shareOptions.isProtected" @click.native="changePassword" icon="pencil-alt">{{ $t('popup_share_edit.change_pass') }}</ActionButton>
|
||||
<ActionButton v-if="(pickedItem.shared.protected && canChangePassword) && shareOptions.isProtected" @click.native="changePassword" class="change-password">{{ $t('popup_share_edit.change_pass') }}</ActionButton>
|
||||
</div>
|
||||
|
||||
<!--Set password-->
|
||||
@@ -40,6 +40,18 @@
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
|
||||
<!--More options-->
|
||||
<div class="more-options" v-if="isMoreOptions">
|
||||
|
||||
<!--Set expiration-->
|
||||
<div class="input-wrapper">
|
||||
<label class="input-label">{{ $t('shared_form.label_expiration') }}:</label>
|
||||
<SelectBoxInput v-model="shareOptions.expiration" :data="expirationList" :value="shareOptions.expiration" class="box"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionButton @click.native="moreOptions" :icon="isMoreOptions || shareOptions.expiration ? 'x' : 'pencil-alt'">{{ moreOptionsTitle }}</ActionButton>
|
||||
|
||||
</ValidationObserver>
|
||||
|
||||
</PopupContent>
|
||||
@@ -68,6 +80,7 @@
|
||||
|
||||
<script>
|
||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
||||
import SelectBoxInput from '@/components/Others/Forms/SelectBoxInput'
|
||||
import PopupWrapper from '@/components/Others/Popup/PopupWrapper'
|
||||
import PopupActions from '@/components/Others/Popup/PopupActions'
|
||||
import PopupContent from '@/components/Others/Popup/PopupContent'
|
||||
@@ -88,6 +101,7 @@
|
||||
components: {
|
||||
ValidationProvider,
|
||||
ValidationObserver,
|
||||
SelectBoxInput,
|
||||
ThumbnailItem,
|
||||
ActionButton,
|
||||
PopupWrapper,
|
||||
@@ -101,7 +115,12 @@
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user', 'permissionOptions', 'currentFolder']),
|
||||
...mapGetters([
|
||||
'permissionOptions',
|
||||
'expirationList',
|
||||
'currentFolder',
|
||||
'user',
|
||||
]),
|
||||
isFolder() {
|
||||
return this.pickedItem && this.pickedItem.type === 'folder'
|
||||
},
|
||||
@@ -114,18 +133,28 @@
|
||||
isSharedLocation() {
|
||||
return this.currentFolder && this.currentFolder.location === 'shared'
|
||||
},
|
||||
moreOptionsTitle() {
|
||||
return this.isMoreOptions ? this.$t('shared_form.button_close_options') : this.$t('shared_form.button_more_options')
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isConfirmedDestroy: false,
|
||||
canChangePassword: false,
|
||||
shareOptions: undefined,
|
||||
pickedItem: undefined,
|
||||
isLoading: false,
|
||||
isMoreOptions: false,
|
||||
isDeleting: false,
|
||||
canChangePassword: false,
|
||||
isConfirmedDestroy: false,
|
||||
isLoading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
moreOptions() {
|
||||
this.isMoreOptions = ! this.isMoreOptions
|
||||
|
||||
if (! this.isMoreOptions)
|
||||
this.shareOptions.expiration = undefined
|
||||
},
|
||||
changePassword() {
|
||||
this.canChangePassword = false
|
||||
},
|
||||
@@ -187,22 +216,22 @@
|
||||
.post('/api/share/' + this.shareOptions.token, {
|
||||
permission: this.shareOptions.permission,
|
||||
protected: this.shareOptions.isProtected,
|
||||
expiration: this.shareOptions.expiration,
|
||||
password: this.shareOptions.password ? this.shareOptions.password : undefined,
|
||||
_method: 'patch'
|
||||
})
|
||||
.then(response => {
|
||||
|
||||
// End loading
|
||||
this.isLoading = false
|
||||
|
||||
// Update shared data
|
||||
this.$store.commit('UPDATE_SHARED_ITEM', response.data.data.attributes)
|
||||
|
||||
events.$emit('popup:close')
|
||||
})
|
||||
.catch(error => {
|
||||
.catch(() => {
|
||||
|
||||
// todo: catch errors
|
||||
this.$isSomethingWrong()
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
// End loading
|
||||
this.isLoading = false
|
||||
@@ -222,11 +251,15 @@
|
||||
// Store shared options
|
||||
this.shareOptions = {
|
||||
token: args.item.shared.token,
|
||||
expiration: args.item.shared.expire_in,
|
||||
isProtected: args.item.shared.protected,
|
||||
permission: args.item.shared.permission,
|
||||
password: undefined,
|
||||
}
|
||||
|
||||
if (args.item.shared.expire_in)
|
||||
this.isMoreOptions = true
|
||||
|
||||
this.canChangePassword = args.item.shared.protected
|
||||
})
|
||||
|
||||
@@ -256,6 +289,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.change-password {
|
||||
opacity: 0.7;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.item-thumbnail {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
2
resources/js/helpers.js
vendored
2
resources/js/helpers.js
vendored
@@ -52,7 +52,7 @@ const Helpers = {
|
||||
}
|
||||
|
||||
Vue.prototype.$getImage = function (source) {
|
||||
return source ? '/' + source : ''
|
||||
return source ? this.$store.getters.config.host + '/' + source : ''
|
||||
}
|
||||
|
||||
Vue.prototype.$getCreditCardBrand = function (brand) {
|
||||
|
||||
@@ -626,6 +626,8 @@
|
||||
"visitor": "仅可以查看或下载文件"
|
||||
},
|
||||
"shared_form": {
|
||||
"button_more_options": "More Options",
|
||||
"button_close_options": "Close Options",
|
||||
"button_done": "太好了!",
|
||||
"button_generate": "生成分享链接",
|
||||
"label_password_protection": "密码保护",
|
||||
|
||||
@@ -626,6 +626,8 @@
|
||||
"visitor": "Can only view and download"
|
||||
},
|
||||
"shared_form": {
|
||||
"button_more_options": "More Options",
|
||||
"button_close_options": "Close Options",
|
||||
"button_done": "Awesome, I’m done!",
|
||||
"button_generate": "Generate Link",
|
||||
"label_password_protection": "Password Protected",
|
||||
|
||||
@@ -626,6 +626,8 @@
|
||||
"visitor": "Môže len vidieť a sťahovať súbory"
|
||||
},
|
||||
"shared_form": {
|
||||
"button_more_options": "Viac nastavení",
|
||||
"button_close_options": "Zavrieť viac možností",
|
||||
"button_done": "Super, som hotový!",
|
||||
"button_generate": "Vygenerovať link",
|
||||
"label_password_protection": "Chrániť heslom",
|
||||
|
||||
33
resources/js/store/modules/app.js
vendored
33
resources/js/store/modules/app.js
vendored
@@ -263,9 +263,39 @@ const defaultState = {
|
||||
{label: 'Zambia', value: 'ZM'},
|
||||
{label: 'Zimbabwe', value: 'ZW'}
|
||||
],
|
||||
expirationList: [
|
||||
{
|
||||
label: i18n.t('shared_form.expiration_hour', {value: 1}),
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: i18n.t('shared_form.expiration_hour', {value: 2}),
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: i18n.t('shared_form.expiration_hour', {value: 6}),
|
||||
value: 6,
|
||||
},
|
||||
{
|
||||
label: i18n.t('shared_form.expiration_hour', {value: 12}),
|
||||
value: 12,
|
||||
},
|
||||
{
|
||||
label: i18n.t('shared_form.expiration_day', {value: 1}),
|
||||
value: 24,
|
||||
},
|
||||
{
|
||||
label: i18n.t('shared_form.expiration_day', {value: 2}),
|
||||
value: 48,
|
||||
},
|
||||
{
|
||||
label: i18n.t('shared_form.expiration_day', {value: 7}),
|
||||
value: 168,
|
||||
},
|
||||
],
|
||||
}
|
||||
const actions = {
|
||||
changePreviewType: ({commit, dispatch, state, getters}) => {
|
||||
changePreviewType: ({commit, state}) => {
|
||||
// Get preview type
|
||||
let previewType = state.FilePreviewType == 'grid' ? 'list' : 'grid'
|
||||
|
||||
@@ -320,6 +350,7 @@ const mutations = {
|
||||
const getters = {
|
||||
fileInfoVisible: state => state.fileInfoPanelVisible,
|
||||
FilePreviewType: state => state.FilePreviewType,
|
||||
expirationList: state => state.expirationList,
|
||||
homeDirectory: state => state.homeDirectory,
|
||||
requestedPlan: state => state.requestedPlan,
|
||||
countries: state => state.countries,
|
||||
|
||||
4
resources/js/store/modules/userAuth.js
vendored
4
resources/js/store/modules/userAuth.js
vendored
@@ -17,6 +17,10 @@ const actions = {
|
||||
.then((response) => {
|
||||
resolve(response)
|
||||
|
||||
// Redirect user if is logged
|
||||
if (router.currentRoute.name === 'SignIn')
|
||||
router.push({ name: 'Files' })
|
||||
|
||||
commit('RETRIEVE_USER', response.data)
|
||||
|
||||
}).catch((error) => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<PageTab :is-loading="isLoading" class="form-fixed-width">
|
||||
|
||||
<!--Personal Information-->
|
||||
<PageTabGroup>
|
||||
<PageTabGroup v-if="! isLoading">
|
||||
<div class="form block-form">
|
||||
<FormLabel>{{ $t('admin_settings.appearance.section_general') }}</FormLabel>
|
||||
|
||||
|
||||
@@ -52,11 +52,11 @@
|
||||
}
|
||||
|
||||
.input-label {
|
||||
@include font-size(12);
|
||||
@include font-size(14);
|
||||
color: $text;
|
||||
font-weight: 700;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
Reference in New Issue
Block a user