mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-29 03:10:51 +00:00
upload request prototype UI
This commit is contained in:
@@ -23,7 +23,13 @@
|
||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">
|
||||
{{ $t('global.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="confirmPassword" button-style="theme" :loading="isLoading" :disabled="isLoading">
|
||||
<ButtonBase
|
||||
class="w-full"
|
||||
@click.native="confirmPassword"
|
||||
button-style="theme"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
{{ $t('popup_2fa.confirm_button') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
|
||||
@@ -39,7 +39,8 @@ export default {
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.isVisibleDisclaimer = this.config.installation === 'installation-done' && !localStorage.getItem('isHiddenDisclaimer')
|
||||
this.isVisibleDisclaimer =
|
||||
this.config.installation === 'installation-done' && !localStorage.getItem('isHiddenDisclaimer')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<AppInputSwitch :title="$t('Emoji as an Icon')" :description="$t('Replace folder icon with an Emoji')" :is-last="!isEmoji">
|
||||
<AppInputSwitch
|
||||
:title="$t('Emoji as an Icon')"
|
||||
:description="$t('Replace folder icon with an Emoji')"
|
||||
:is-last="!isEmoji"
|
||||
>
|
||||
<SwitchInput v-model="isEmoji" :state="isEmoji" />
|
||||
</AppInputSwitch>
|
||||
|
||||
@@ -32,8 +36,12 @@
|
||||
|
||||
<!--Actions-->
|
||||
<PopupActions>
|
||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">{{ $t('popup_move_item.cancel') }} </ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="createFolder" button-style="theme">{{ $t('popup_create_folder.title') }} </ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
|
||||
>{{ $t('popup_move_item.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="createFolder" button-style="theme"
|
||||
>{{ $t('popup_create_folder.title') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
</PopupWrapper>
|
||||
</template>
|
||||
|
||||
@@ -7,9 +7,20 @@
|
||||
<PopupContent>
|
||||
<!--Form to set sharing-->
|
||||
<ValidationObserver @submit.prevent="createLanguage" ref="createForm" v-slot="{ invalid }" tag="form">
|
||||
<ValidationProvider tag="div" mode="passive" name="Language Locale" rules="required" v-slot="{ errors }">
|
||||
<ValidationProvider
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="Language Locale"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<AppInputText :title="$t('select_locale')" :error="errors[0]">
|
||||
<SelectInput v-model="form.locale" :options="locales" :placeholder="$t('select_language_locale')" :isError="errors[0]" />
|
||||
<SelectInput
|
||||
v-model="form.locale"
|
||||
:options="locales"
|
||||
:placeholder="$t('select_language_locale')"
|
||||
:isError="errors[0]"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
<ValidationProvider tag="div" mode="passive" name="Language Name" rules="required" v-slot="{ errors }">
|
||||
@@ -32,7 +43,13 @@
|
||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">
|
||||
{{ $t('global.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="createLanguage" button-style="theme" :loading="isLoading" :disabled="isLoading">
|
||||
<ButtonBase
|
||||
class="w-full"
|
||||
@click.native="createLanguage"
|
||||
button-style="theme"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
{{ $t('create_language') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
|
||||
@@ -3,7 +3,13 @@
|
||||
<PopupHeader :title="$t('popup_personal_token.title')" icon="key" />
|
||||
|
||||
<PopupContent>
|
||||
<ValidationObserver v-if="!token" @submit.prevent="createTokenForm" ref="createToken" v-slot="{ invalid }" tag="form">
|
||||
<ValidationObserver
|
||||
v-if="!token"
|
||||
@submit.prevent="createTokenForm"
|
||||
ref="createToken"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
>
|
||||
<ValidationProvider tag="div" mode="passive" name="Token Name" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('popup_personal_token.label')" :error="errors[0]" :is-last="true">
|
||||
<input
|
||||
@@ -31,7 +37,13 @@
|
||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">
|
||||
{{ $t('global.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="createTokenForm" button-style="theme" :loading="isLoading" :disabled="isLoading">
|
||||
<ButtonBase
|
||||
class="w-full"
|
||||
@click.native="createTokenForm"
|
||||
button-style="theme"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
{{ $t('personal_token.create_token') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div v-if="emoji">
|
||||
<div v-if="config.defaultEmoji === 'twemoji'" v-html="transferEmoji" style="font-size: inherit; transform: scale(0.95)"></div>
|
||||
<div
|
||||
v-if="config.defaultEmoji === 'twemoji'"
|
||||
v-html="transferEmoji"
|
||||
style="font-size: inherit; transform: scale(0.95)"
|
||||
></div>
|
||||
<div v-if="config.defaultEmoji === 'applemoji'" style="font-size: inherit">
|
||||
{{ emoji.char }}
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,13 @@
|
||||
</div>
|
||||
|
||||
<!-- Search input -->
|
||||
<input @click="openList" v-model="query" class="focus-border-theme input-dark" type="text" :placeholder="$t('Select or search emoji icon...')" />
|
||||
<input
|
||||
@click="openList"
|
||||
v-model="query"
|
||||
class="focus-border-theme input-dark"
|
||||
type="text"
|
||||
:placeholder="$t('Select or search emoji icon...')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Spinner -->
|
||||
@@ -17,9 +23,18 @@
|
||||
</div>
|
||||
|
||||
<!-- Emojis List -->
|
||||
<div v-if="isOpen && isLoaded && emojis" @scroll="checkGroupInView" id="group-box" class="relative h-96 select-none overflow-y-auto lg:h-60 2xl:h-96">
|
||||
<div
|
||||
v-if="isOpen && isLoaded && emojis"
|
||||
@scroll="checkGroupInView"
|
||||
id="group-box"
|
||||
class="relative h-96 select-none overflow-y-auto lg:h-60 2xl:h-96"
|
||||
>
|
||||
<!-- Navigation of Emojis Groups -->
|
||||
<ul v-if="!query" class="sticky top-0 z-10 flex items-center justify-between space-x-1 bg-white dark:bg-dark-background sm:dark:bg-4x-dark-foreground" id="group-bar">
|
||||
<ul
|
||||
v-if="!query"
|
||||
class="sticky top-0 z-10 flex items-center justify-between space-x-1 bg-white dark:bg-dark-background sm:dark:bg-4x-dark-foreground"
|
||||
id="group-bar"
|
||||
>
|
||||
<li
|
||||
@click.stop="scrollToGroup(group.name)"
|
||||
v-for="(group, i) in emojis.groups"
|
||||
@@ -39,7 +54,12 @@
|
||||
{{ name }}
|
||||
</label>
|
||||
<ul class="space-between grid grid-cols-7 gap-4 md:grid-cols-9">
|
||||
<li @click="setEmoji(emoji)" v-for="(emoji, i) in group" :key="i" class="flex cursor-pointer items-center justify-center">
|
||||
<li
|
||||
@click="setEmoji(emoji)"
|
||||
v-for="(emoji, i) in group"
|
||||
:key="i"
|
||||
class="flex cursor-pointer items-center justify-center"
|
||||
>
|
||||
<Emoji :emoji="emoji" class="text-4xl" />
|
||||
</li>
|
||||
</ul>
|
||||
@@ -47,7 +67,12 @@
|
||||
|
||||
<!-- Searched emojis -->
|
||||
<ul v-if="query" class="space-between grid grid-cols-7 gap-4 md:grid-cols-9">
|
||||
<li @click="setEmoji(emoji)" v-for="(emoji, i) in filteredEmojis" :key="i" class="flex cursor-pointer items-center justify-center">
|
||||
<li
|
||||
@click="setEmoji(emoji)"
|
||||
v-for="(emoji, i) in filteredEmojis"
|
||||
:key="i"
|
||||
class="flex cursor-pointer items-center justify-center"
|
||||
>
|
||||
<Emoji :emoji="emoji" class="text-4xl" />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -9,10 +9,24 @@
|
||||
/>
|
||||
|
||||
<!--Audio-->
|
||||
<audio v-if="singleFile.data.type === 'audio'" :src="singleFile.data.attributes.file_url" controlsList="nodownload" controls class="w-full"></audio>
|
||||
<audio
|
||||
v-if="singleFile.data.type === 'audio'"
|
||||
:src="singleFile.data.attributes.file_url"
|
||||
controlsList="nodownload"
|
||||
controls
|
||||
class="w-full"
|
||||
></audio>
|
||||
|
||||
<!--Video-->
|
||||
<video v-if="singleFile.data.type === 'video'" ref="video" class="h-auto w-full overflow-hidden rounded-sm" controlsList="nodownload" disablePictureInPicture playsinline controls>
|
||||
<video
|
||||
v-if="singleFile.data.type === 'video'"
|
||||
ref="video"
|
||||
class="h-auto w-full overflow-hidden rounded-sm"
|
||||
controlsList="nodownload"
|
||||
disablePictureInPicture
|
||||
playsinline
|
||||
controls
|
||||
>
|
||||
<source :src="singleFile.data.attributes.file_url" type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
@@ -33,12 +47,12 @@ export default {
|
||||
return this.singleFile && !includes(['folder', 'file'], this.singleFile.data.type)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'singleFile': function (val) {
|
||||
if (val.data.type === 'video') {
|
||||
this.$refs.video.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
watch: {
|
||||
singleFile: function (val) {
|
||||
if (val.data.type === 'video') {
|
||||
this.$refs.video.load()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
<template>
|
||||
<div class="relative cursor-pointer">
|
||||
<input ref="file" type="file" @change="showImagePreview($event)" class="absolute top-0 bottom-0 left-0 right-0 z-10 w-full cursor-pointer opacity-0" />
|
||||
<img v-if="imagePreview" ref="image" :src="imagePreview" class="relative z-0 h-14 w-14 cursor-pointer rounded-xl object-cover shadow-lg md:h-16 md:w-16" alt="avatar" />
|
||||
<input
|
||||
ref="file"
|
||||
type="file"
|
||||
@change="showImagePreview($event)"
|
||||
class="absolute top-0 bottom-0 left-0 right-0 z-10 w-full cursor-pointer opacity-0"
|
||||
/>
|
||||
<img
|
||||
v-if="imagePreview"
|
||||
ref="image"
|
||||
:src="imagePreview"
|
||||
class="relative z-0 h-14 w-14 cursor-pointer rounded-xl object-cover shadow-lg md:h-16 md:w-16"
|
||||
alt="avatar"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
</div>
|
||||
|
||||
<!--Hidden options-->
|
||||
<ul v-if="isOpenedMoreOptions" class="absolute top-12 left-0 right-0 z-10 select-none overflow-y-auto overflow-x-hidden rounded-lg shadow-xl">
|
||||
<ul
|
||||
v-if="isOpenedMoreOptions"
|
||||
class="absolute top-12 left-0 right-0 z-10 select-none overflow-y-auto overflow-x-hidden rounded-lg shadow-xl"
|
||||
>
|
||||
<li
|
||||
@click="getQrCode"
|
||||
class="block flex cursor-pointer items-center bg-white py-2.5 px-5 hover:bg-light-background dark:bg-2x-dark-foreground dark:hover:bg-4x-dark-foreground"
|
||||
@@ -57,7 +60,11 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<textarea v-model="iframeCode" ref="iframe" class="pointer-events-none absolute right-full opacity-0"></textarea>
|
||||
<textarea
|
||||
v-model="iframeCode"
|
||||
ref="iframe"
|
||||
class="pointer-events-none absolute right-full opacity-0"
|
||||
></textarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
<script>
|
||||
import {
|
||||
InfoIcon,
|
||||
DatabaseIcon,
|
||||
InfoIcon,
|
||||
DatabaseIcon,
|
||||
UsersIcon,
|
||||
ShieldIcon,
|
||||
CreditCardIcon,
|
||||
@@ -44,8 +44,8 @@ export default {
|
||||
name: 'FormLabel',
|
||||
props: ['icon'],
|
||||
components: {
|
||||
InfoIcon,
|
||||
DatabaseIcon,
|
||||
InfoIcon,
|
||||
DatabaseIcon,
|
||||
UsersIcon,
|
||||
CreditCardIcon,
|
||||
DollarSignIcon,
|
||||
|
||||
@@ -1,86 +1,97 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center rounded-lg relative h-[175px] dark:bg-2x-dark-foreground bg-light-background" :class="{ 'is-error': error }">
|
||||
|
||||
<!--Reset Image-->
|
||||
<div
|
||||
v-if="imagePreview"
|
||||
@click="resetImage"
|
||||
class="absolute z-10 right-0 top-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-md bg-white shadow-lg rounded-full -translate-y-3 translate-x-3"
|
||||
>
|
||||
<div
|
||||
class="relative flex h-[175px] items-center justify-center rounded-lg bg-light-background dark:bg-2x-dark-foreground"
|
||||
:class="{ 'is-error': error }"
|
||||
>
|
||||
<!--Reset Image-->
|
||||
<div
|
||||
v-if="imagePreview"
|
||||
@click="resetImage"
|
||||
class="absolute right-0 top-0 z-10 flex h-7 w-7 -translate-y-3 translate-x-3 cursor-pointer items-center justify-center rounded-md rounded-full bg-white shadow-lg"
|
||||
>
|
||||
<x-icon size="14" class="vue-feather" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
@change="showImagePreview($event)"
|
||||
ref="file"
|
||||
type="file"
|
||||
class="opacity-0 absolute top-0 left-0 right-0 bottom-0 z-10 w-full cursor-pointer"
|
||||
/>
|
||||
@change="showImagePreview($event)"
|
||||
ref="file"
|
||||
type="file"
|
||||
class="absolute top-0 left-0 right-0 bottom-0 z-10 w-full cursor-pointer opacity-0"
|
||||
/>
|
||||
|
||||
<!--Default image preview-->
|
||||
<img v-if="imagePreview" :src="imagePreview" ref="image" class="absolute w-full h-full object-contain py-4 px-12" />
|
||||
<!--Default image preview-->
|
||||
<img
|
||||
v-if="imagePreview"
|
||||
:src="imagePreview"
|
||||
ref="image"
|
||||
class="absolute h-full w-full object-contain py-4 px-12"
|
||||
/>
|
||||
|
||||
<!--Drop image zone-->
|
||||
<!--Drop image zone-->
|
||||
<div v-if="!isData" class="text-center">
|
||||
<image-icon size="34" class="vue-feather text-theme inline-block mb-4" />
|
||||
<image-icon size="34" class="vue-feather text-theme mb-4 inline-block" />
|
||||
|
||||
<b class="font-bold text-base block leading-3">
|
||||
<b class="block text-base font-bold leading-3">
|
||||
{{ $te('input_image.title') ? $t('input_image.title') : 'Upload Image' }}
|
||||
</b>
|
||||
<small class="text-xs text-gray-500">
|
||||
{{ $te('input_image.supported') ? $t('input_image.supported') : 'Supported formats are .png, .jpg, .jpeg.' }}
|
||||
{{
|
||||
$te('input_image.supported')
|
||||
? $t('input_image.supported')
|
||||
: 'Supported formats are .png, .jpg, .jpeg.'
|
||||
}}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {XIcon, ImageIcon} from 'vue-feather-icons'
|
||||
import { XIcon, ImageIcon } from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'ImageInput',
|
||||
props: ['image', 'error'],
|
||||
components: {
|
||||
ImageIcon,
|
||||
XIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imagePreview: undefined,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isData() {
|
||||
return !(typeof this.imagePreview === 'undefined' || this.imagePreview === '')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resetImage() {
|
||||
this.imagePreview = undefined
|
||||
this.$emit('input', undefined)
|
||||
},
|
||||
showImagePreview(event) {
|
||||
const imgPath = event.target.files[0].name,
|
||||
extn = imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase()
|
||||
name: 'ImageInput',
|
||||
props: ['image', 'error'],
|
||||
components: {
|
||||
ImageIcon,
|
||||
XIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imagePreview: undefined,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isData() {
|
||||
return !(typeof this.imagePreview === 'undefined' || this.imagePreview === '')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resetImage() {
|
||||
this.imagePreview = undefined
|
||||
this.$emit('input', undefined)
|
||||
},
|
||||
showImagePreview(event) {
|
||||
const imgPath = event.target.files[0].name,
|
||||
extn = imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase()
|
||||
|
||||
if (['png', 'jpg', 'jpeg', 'svg'].includes(extn)) {
|
||||
const file = event.target.files[0],
|
||||
reader = new FileReader()
|
||||
if (['png', 'jpg', 'jpeg', 'svg'].includes(extn)) {
|
||||
const file = event.target.files[0],
|
||||
reader = new FileReader()
|
||||
|
||||
reader.onload = () => (this.imagePreview = reader.result)
|
||||
reader.onload = () => (this.imagePreview = reader.result)
|
||||
|
||||
reader.readAsDataURL(file)
|
||||
reader.readAsDataURL(file)
|
||||
|
||||
// Update user avatar
|
||||
this.$emit('input', event.target.files[0])
|
||||
} else {
|
||||
alert(this.$t('validation_errors.wrong_image'))
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// If has default image then load
|
||||
if (this.image) this.imagePreview = this.image
|
||||
},
|
||||
// Update user avatar
|
||||
this.$emit('input', event.target.files[0])
|
||||
} else {
|
||||
alert(this.$t('validation_errors.wrong_image'))
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// If has default image then load
|
||||
if (this.image) this.imagePreview = this.image
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'InfoBox',
|
||||
props: [
|
||||
'type'
|
||||
],
|
||||
props: ['type'],
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<!--<label class="input-label">{{ label }}:</label>-->
|
||||
<div class="input-wrapper focus-within-border-theme" :class="{ 'is-error': isError }" @click="$refs.input.focus()">
|
||||
<div
|
||||
class="input-wrapper focus-within-border-theme"
|
||||
:class="{ 'is-error': isError }"
|
||||
@click="$refs.input.focus()"
|
||||
>
|
||||
<div class="email-list">
|
||||
<div class="email-tag bg-theme-100" :class="{ 'mb-offset': getCharactersLength > 45 }" v-for="(email, i) in emails" :key="i">
|
||||
<div
|
||||
class="email-tag bg-theme-100"
|
||||
:class="{ 'mb-offset': getCharactersLength > 45 }"
|
||||
v-for="(email, i) in emails"
|
||||
:key="i"
|
||||
>
|
||||
<span class="text-theme">{{ email }}</span>
|
||||
<x-icon @click="removeEmail(email)" class="icon" size="14" />
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,14 @@
|
||||
<div @click="clearInput" v-if="query" class="icon">
|
||||
<x-icon class="pointer" size="19"></x-icon>
|
||||
</div>
|
||||
<input v-model="query" @input="$emit('input', query)" class="query focus-border-theme" type="text" name="searchInput" :placeholder="$t('search_translations')" />
|
||||
<input
|
||||
v-model="query"
|
||||
@input="$emit('input', query)"
|
||||
class="query focus-border-theme"
|
||||
type="text"
|
||||
name="searchInput"
|
||||
:placeholder="$t('search_translations')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<template>
|
||||
<div class="select-box">
|
||||
<div class="box-item active-bg-theme-100 active-border-theme" :class="{ active: item.value === input }" @click="getSelectedValue(item)" v-for="(item, i) in data" :key="i">
|
||||
<div
|
||||
class="box-item active-bg-theme-100 active-border-theme"
|
||||
:class="{ active: item.value === input }"
|
||||
@click="getSelectedValue(item)"
|
||||
v-for="(item, i) in data"
|
||||
:key="i"
|
||||
>
|
||||
<span class="box-value active-text-theme">{{ item.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<div class="select">
|
||||
<!--Area-->
|
||||
<div class="input-area rounded-lg dark:bg-2x-dark-foreground bg-light-background" :class="{ 'is-active': isOpen, 'is-error': isError }" @click="openMenu">
|
||||
<div
|
||||
class="input-area rounded-lg bg-light-background dark:bg-2x-dark-foreground"
|
||||
:class="{ 'is-active': isOpen, 'is-error': isError }"
|
||||
@click="openMenu"
|
||||
>
|
||||
<!--If is selected-->
|
||||
<div class="selected flex w-full items-center" v-if="selected">
|
||||
<div class="option-icon" v-if="selected.icon">
|
||||
@@ -25,7 +29,13 @@
|
||||
<transition name="slide-in">
|
||||
<div class="input-options rounded-lg" v-if="isOpen">
|
||||
<div v-if="options.length > 5" class="select-search">
|
||||
<input v-model="query" ref="search" type="text" :placeholder="$t('select_search_placeholder')" class="search-input focus-border-theme rounded-lg" />
|
||||
<input
|
||||
v-model="query"
|
||||
ref="search"
|
||||
type="text"
|
||||
:placeholder="$t('select_search_placeholder')"
|
||||
class="search-input focus-border-theme rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<ul class="option-list">
|
||||
<li class="option-item" @click="selectOption(option)" v-for="(option, i) in optionList" :key="i">
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
<UserHeadline v-if="!clickedSubmenu" class="p-5 pb-3" />
|
||||
|
||||
<!--User estimate-->
|
||||
<div v-if="config.subscriptionType === 'metered' && user && user.data.meta.usages && !clickedSubmenu" class="block px-5 pt-2">
|
||||
<div
|
||||
v-if="config.subscriptionType === 'metered' && user && user.data.meta.usages && !clickedSubmenu"
|
||||
class="block px-5 pt-2"
|
||||
>
|
||||
<div class="rounded-lg bg-light-background px-3 py-1.5 dark:bg-4x-dark-foreground">
|
||||
<span class="text-sm font-semibold">
|
||||
{{ $t('Your current estimated usage:') }}
|
||||
@@ -27,9 +30,27 @@
|
||||
<MenuMobileGroup>
|
||||
<!--Main navigation-->
|
||||
<OptionGroup v-if="!clickedSubmenu">
|
||||
<Option @click.native="goToFiles" :title="$t('menu.files')" icon="hard-drive" :is-hover-disabled="true" />
|
||||
<Option @click.native.stop="showSubmenu('settings')" :title="$t('menu.settings')" icon="user" arrow="right" :is-hover-disabled="true" />
|
||||
<Option v-if="isAdmin" @click.native.stop="showSubmenu('admin')" :title="$t('menu.admin')" icon="settings" arrow="right" :is-hover-disabled="true" />
|
||||
<Option
|
||||
@click.native="goToFiles"
|
||||
:title="$t('menu.files')"
|
||||
icon="hard-drive"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native.stop="showSubmenu('settings')"
|
||||
:title="$t('menu.settings')"
|
||||
icon="user"
|
||||
arrow="right"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
v-if="isAdmin"
|
||||
@click.native.stop="showSubmenu('admin')"
|
||||
:title="$t('menu.admin')"
|
||||
icon="settings"
|
||||
arrow="right"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
</OptionGroup>
|
||||
<OptionGroup v-if="!clickedSubmenu">
|
||||
<Option @click.native="logOut" :title="$t('menu.logout')" icon="power" :is-hover-disabled="true" />
|
||||
@@ -37,28 +58,79 @@
|
||||
|
||||
<!--Submenu: User settings-->
|
||||
<OptionGroup v-if="clickedSubmenu === 'settings'">
|
||||
<Option @click.native="goToRoute('Profile')" :title="$t('menu.profile')" icon="user" :is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Password')" :title="$t('menu.password')" icon="lock" :is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Storage')" :title="$t('menu.storage')" icon="hard-drive" :is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Billing')" v-if="config.subscriptionType !== 'none'" :title="$t('Billing')" icon="cloud" :is-hover-disabled="true" />
|
||||
<Option
|
||||
@click.native="goToRoute('Profile')"
|
||||
:title="$t('menu.profile')"
|
||||
icon="user"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('Password')"
|
||||
:title="$t('menu.password')"
|
||||
icon="lock"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('Storage')"
|
||||
:title="$t('menu.storage')"
|
||||
icon="hard-drive"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('Billing')"
|
||||
v-if="config.subscriptionType !== 'none'"
|
||||
:title="$t('Billing')"
|
||||
icon="cloud"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
</OptionGroup>
|
||||
|
||||
<!--Submenu: Admin settings-->
|
||||
<OptionGroup v-if="clickedSubmenu === 'admin'">
|
||||
<Option @click.native="goToRoute('Dashboard')" :title="$t('admin_menu.dashboard')" icon="box" :is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Users')" :title="$t('admin_menu.users')" icon="users" :is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('AppOthers')" :title="$t('admin_menu.settings')" icon="settings" :is-hover-disabled="true" />
|
||||
<Option
|
||||
@click.native="goToRoute('Dashboard')"
|
||||
:title="$t('admin_menu.dashboard')"
|
||||
icon="box"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('Users')"
|
||||
:title="$t('admin_menu.users')"
|
||||
icon="users"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('AppOthers')"
|
||||
:title="$t('admin_menu.settings')"
|
||||
icon="settings"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
</OptionGroup>
|
||||
|
||||
<!--Submenu: Content settings-->
|
||||
<OptionGroup v-if="clickedSubmenu === 'admin'">
|
||||
<Option @click.native="goToRoute('Pages')" :title="$t('admin_menu.pages')" icon="monitor" :is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Language')" :title="$t('languages')" icon="globe" :is-hover-disabled="true" />
|
||||
<Option
|
||||
@click.native="goToRoute('Pages')"
|
||||
:title="$t('admin_menu.pages')"
|
||||
icon="monitor"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('Language')"
|
||||
:title="$t('languages')"
|
||||
icon="globe"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
</OptionGroup>
|
||||
|
||||
<!--Submenu: Billing settings-->
|
||||
<OptionGroup v-if="clickedSubmenu === 'admin' && config.subscriptionType !== 'none'">
|
||||
<Option @click.native="goToRoute('AppPayments')" :title="$t('Payments')" icon="credit-card" :is-hover-disabled="true" />
|
||||
<Option
|
||||
@click.native="goToRoute('AppPayments')"
|
||||
:title="$t('Payments')"
|
||||
icon="credit-card"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('Subscriptions')"
|
||||
v-if="config.subscriptionType === 'fixed'"
|
||||
@@ -66,8 +138,18 @@
|
||||
icon="credit-card"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option @click.native="goToRoute('Plans')" :title="$t('admin_menu.plans')" icon="database" :is-hover-disabled="true" />
|
||||
<Option @click.native="goToRoute('Invoices')" :title="$t('Transactions')" icon="file-text" :is-hover-disabled="true" />
|
||||
<Option
|
||||
@click.native="goToRoute('Plans')"
|
||||
:title="$t('admin_menu.plans')"
|
||||
icon="database"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
<Option
|
||||
@click.native="goToRoute('Invoices')"
|
||||
:title="$t('Transactions')"
|
||||
icon="file-text"
|
||||
:is-hover-disabled="true"
|
||||
/>
|
||||
</OptionGroup>
|
||||
</MenuMobileGroup>
|
||||
</MenuMobile>
|
||||
|
||||
@@ -20,14 +20,25 @@
|
||||
v-if="clipboard.length > 1 && !isSelectedItem"
|
||||
/>
|
||||
|
||||
<TreeMenu class="-mx-4" :disabled-by-id="pickedItem" :depth="1" :nodes="items" v-for="items in navigation" :key="items.id" />
|
||||
<TreeMenu
|
||||
class="-mx-4"
|
||||
:disabled-by-id="pickedItem"
|
||||
:depth="1"
|
||||
:nodes="items"
|
||||
v-for="items in navigation"
|
||||
:key="items.id"
|
||||
/>
|
||||
</div>
|
||||
</PopupContent>
|
||||
|
||||
<!--Actions-->
|
||||
<PopupActions>
|
||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">{{ $t('popup_move_item.cancel') }} </ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="moveItem" :button-style="selectedFolder ? 'theme' : 'secondary'">{{ $t('popup_move_item.submit') }} </ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
|
||||
>{{ $t('popup_move_item.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="moveItem" :button-style="selectedFolder ? 'theme' : 'secondary'"
|
||||
>{{ $t('popup_move_item.submit') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
</PopupWrapper>
|
||||
</template>
|
||||
@@ -76,7 +87,11 @@ export default {
|
||||
if (!this.selectedFolder) return
|
||||
|
||||
// Prevent to move items to the same parent
|
||||
if (isArray(this.selectedFolder) && this.clipboard.find((item) => item.parent_id === this.selectedFolder.id)) return
|
||||
if (
|
||||
isArray(this.selectedFolder) &&
|
||||
this.clipboard.find((item) => item.parent_id === this.selectedFolder.id)
|
||||
)
|
||||
return
|
||||
|
||||
// Move item
|
||||
if (!this.isSelectedItem) {
|
||||
|
||||
@@ -18,9 +18,16 @@
|
||||
<footer class="plan-footer">
|
||||
<b class="price text-theme">
|
||||
{{ plan.data.attributes.price }}/{{ $t('global.monthly_ac') }}
|
||||
<small v-if="plan.data.attributes.tax_rates.length > 0" class="vat-disclaimer">{{ $t('page_pricing_tables.vat_excluded') }}</small>
|
||||
<small v-if="plan.data.attributes.tax_rates.length > 0" class="vat-disclaimer">{{
|
||||
$t('page_pricing_tables.vat_excluded')
|
||||
}}</small>
|
||||
</b>
|
||||
<ButtonBase @click.native="selectPlan(plan)" type="submit" button-style="secondary" class="sign-in-button">
|
||||
<ButtonBase
|
||||
@click.native="selectPlan(plan)"
|
||||
type="submit"
|
||||
button-style="secondary"
|
||||
class="sign-in-button"
|
||||
>
|
||||
{{ $t('global.get_it') }}
|
||||
</ButtonBase>
|
||||
</footer>
|
||||
|
||||
@@ -14,8 +14,12 @@
|
||||
</div>
|
||||
|
||||
<PopupActions>
|
||||
<ButtonBase @click.native="closePopup" button-style="secondary" class="w-full">{{ $t('global.cancel') }} </ButtonBase>
|
||||
<ButtonBase @click.native="confirm" :button-style="buttonColor" class="w-full">{{ $t('global.confirm_action') }} </ButtonBase>
|
||||
<ButtonBase @click.native="closePopup" button-style="secondary" class="w-full"
|
||||
>{{ $t('global.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase @click.native="confirm" :button-style="buttonColor" class="w-full"
|
||||
>{{ $t('global.confirm_action') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
</PopupWrapper>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div :class="type" class="absolute top-16 bottom-24 left-0 right-0 h-auto overflow-x-auto overflow-y-auto px-6 md:relative md:top-0 md:bottom-0">
|
||||
<div
|
||||
:class="type"
|
||||
class="absolute top-16 bottom-24 left-0 right-0 h-auto overflow-x-auto overflow-y-auto px-6 md:relative md:top-0 md:bottom-0"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -22,7 +22,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { CreditCardIcon, KeyIcon, UserPlusIcon, CornerDownRightIcon, LinkIcon, XIcon, Edit2Icon, ShareIcon, UsersIcon } from 'vue-feather-icons'
|
||||
import {
|
||||
CreditCardIcon,
|
||||
KeyIcon,
|
||||
UserPlusIcon,
|
||||
CornerDownRightIcon,
|
||||
LinkIcon,
|
||||
XIcon,
|
||||
Edit2Icon,
|
||||
ShareIcon,
|
||||
UsersIcon,
|
||||
} from 'vue-feather-icons'
|
||||
import { events } from '../../../bus'
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<transition name="popup">
|
||||
<div v-if="isVisibleWrapper" @click.self="closePopup" class="popup z-50 fixed top-0 left-0 right-0 bottom-0 grid h-full overflow-y-auto p-10 lg:absolute">
|
||||
<div class="fixed md:relative top-0 bottom-0 left-0 right-0 w-full dark:bg-2x-dark-foreground bg-white m-auto z-10 md:w-[490px] md:rounded-xl shadow-xl">
|
||||
<div
|
||||
v-if="isVisibleWrapper"
|
||||
@click.self="closePopup"
|
||||
class="popup fixed top-0 left-0 right-0 bottom-0 z-50 grid h-full overflow-y-auto p-10 lg:absolute"
|
||||
>
|
||||
<div
|
||||
class="fixed top-0 bottom-0 left-0 right-0 z-10 m-auto w-full bg-white shadow-xl dark:bg-2x-dark-foreground md:relative md:w-[490px] md:rounded-xl"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,41 +50,40 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.popup-leave-active {
|
||||
animation: popup-slide-in 0.15s ease reverse;
|
||||
}
|
||||
|
||||
.popup-leave-active {
|
||||
animation: popup-slide-in 0.15s ease reverse;
|
||||
}
|
||||
@media only screen and (min-width: 960px) {
|
||||
.popup-enter-active {
|
||||
animation: popup-slide-in 0.25s 0.1s ease both;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 960px) {
|
||||
.popup-enter-active {
|
||||
animation: popup-slide-in 0.25s 0.10s ease both;
|
||||
}
|
||||
@keyframes popup-slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(100px);
|
||||
}
|
||||
|
||||
@keyframes popup-slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(100px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 960px) {
|
||||
.popup-enter-active {
|
||||
animation: popup-slide-in 0.35s 0.15s ease both;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
.popup-enter-active {
|
||||
animation: popup-slide-in 0.35s 0.15s ease both;
|
||||
}
|
||||
|
||||
@keyframes popup-slide-in {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes popup-slide-in {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,7 +12,11 @@
|
||||
<ValidationObserver @submit.prevent="changeName" ref="renameForm" v-slot="{ invalid }" tag="form">
|
||||
<!--Update item name-->
|
||||
<ValidationProvider tag="div" mode="passive" name="Name" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('popup_rename.label')" :error="errors[0]" :is-last="pickedItem.data.type !== 'folder'">
|
||||
<AppInputText
|
||||
:title="$t('popup_rename.label')"
|
||||
:error="errors[0]"
|
||||
:is-last="pickedItem.data.type !== 'folder'"
|
||||
>
|
||||
<div class="relative flex items-center">
|
||||
<input
|
||||
v-model="pickedItem.data.attributes.name"
|
||||
@@ -30,12 +34,21 @@
|
||||
</ValidationProvider>
|
||||
|
||||
<!--Emoji-->
|
||||
<AppInputSwitch v-if="pickedItem.data.type === 'folder'" :title="$t('Emoji as an Icon')" :description="$t('Replace folder icon with an Emoji')" :is-last="!isEmoji">
|
||||
<AppInputSwitch
|
||||
v-if="pickedItem.data.type === 'folder'"
|
||||
:title="$t('Emoji as an Icon')"
|
||||
:description="$t('Replace folder icon with an Emoji')"
|
||||
:is-last="!isEmoji"
|
||||
>
|
||||
<SwitchInput v-model="isEmoji" :state="isEmoji" />
|
||||
</AppInputSwitch>
|
||||
|
||||
<!--Set emoji-->
|
||||
<EmojiPicker v-if="pickedItem.data.type === 'folder' && isEmoji" v-model="emoji" :default-emoji="emoji" />
|
||||
<EmojiPicker
|
||||
v-if="pickedItem.data.type === 'folder' && isEmoji"
|
||||
v-model="emoji"
|
||||
:default-emoji="emoji"
|
||||
/>
|
||||
</ValidationObserver>
|
||||
</PopupContent>
|
||||
|
||||
@@ -87,7 +100,9 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
itemTypeTitle() {
|
||||
return this.pickedItem && this.pickedItem.data.type === 'folder' ? this.$t('types.folder') : this.$t('types.file')
|
||||
return this.pickedItem && this.pickedItem.data.type === 'folder'
|
||||
? this.$t('types.folder')
|
||||
: this.$t('types.file')
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
||||
@@ -10,11 +10,19 @@
|
||||
'mb-2 rounded-xl bg-light-background px-4 dark:bg-2x-dark-foreground': paypal.isMethodsLoaded,
|
||||
}"
|
||||
>
|
||||
<PaymentMethod @click.native="pickedPaymentMethod('paypal')" driver="paypal" :description="config.paypal_payment_description">
|
||||
<PaymentMethod
|
||||
@click.native="pickedPaymentMethod('paypal')"
|
||||
driver="paypal"
|
||||
:description="config.paypal_payment_description"
|
||||
>
|
||||
<div v-if="paypal.isMethodLoading" class="translate-y-3 scale-50 transform">
|
||||
<Spinner />
|
||||
</div>
|
||||
<span v-if="!paypal.isMethodsLoaded" :class="{ 'opacity-0': paypal.isMethodLoading }" class="text-theme cursor-pointer text-sm font-bold">
|
||||
<span
|
||||
v-if="!paypal.isMethodsLoaded"
|
||||
:class="{ 'opacity-0': paypal.isMethodLoading }"
|
||||
class="text-theme cursor-pointer text-sm font-bold"
|
||||
>
|
||||
{{ $t('Select') }}
|
||||
</span>
|
||||
</PaymentMethod>
|
||||
@@ -24,7 +32,11 @@
|
||||
</div>
|
||||
|
||||
<!--Paystack implementation-->
|
||||
<PaymentMethod v-if="config.isPaystack" driver="paystack" :description="config.paystack_payment_description">
|
||||
<PaymentMethod
|
||||
v-if="config.isPaystack"
|
||||
driver="paystack"
|
||||
:description="config.paystack_payment_description"
|
||||
>
|
||||
<paystack
|
||||
@click.native="pickedPaymentMethod('paystack')"
|
||||
v-if="user && config"
|
||||
|
||||
@@ -9,9 +9,22 @@
|
||||
<ThumbnailItem class="mb-5" :item="pickedItem" />
|
||||
|
||||
<!--Form to set sharing-->
|
||||
<ValidationObserver v-if="!isGeneratedShared" @submit.prevent ref="shareForm" v-slot="{ invalid }" tag="form">
|
||||
<ValidationObserver
|
||||
v-if="!isGeneratedShared"
|
||||
@submit.prevent
|
||||
ref="shareForm"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
>
|
||||
<!--Permission Select-->
|
||||
<ValidationProvider v-if="isFolder" tag="div" mode="passive" name="Permission" rules="required" v-slot="{ errors }">
|
||||
<ValidationProvider
|
||||
v-if="isFolder"
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="Permission"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<AppInputText :title="$t('shared_form.label_permission')" :error="errors[0]">
|
||||
<SelectInput
|
||||
v-model="shareOptions.permission"
|
||||
@@ -24,12 +37,26 @@
|
||||
|
||||
<!--Password Switch-->
|
||||
<div>
|
||||
<AppInputSwitch :title="$t('shared_form.label_password_protection')" :description="$t('popup.share.password_description')">
|
||||
<SwitchInput v-model="shareOptions.isPassword" class="switch" :state="shareOptions.isPassword" />
|
||||
<AppInputSwitch
|
||||
:title="$t('shared_form.label_password_protection')"
|
||||
:description="$t('popup.share.password_description')"
|
||||
>
|
||||
<SwitchInput
|
||||
v-model="shareOptions.isPassword"
|
||||
class="switch"
|
||||
:state="shareOptions.isPassword"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<!--Set password-->
|
||||
<ValidationProvider v-if="shareOptions.isPassword" tag="div" mode="passive" name="Password" rules="required" v-slot="{ errors }">
|
||||
<ValidationProvider
|
||||
v-if="shareOptions.isPassword"
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="Password"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<AppInputText :error="errors[0]" class="-mt-2">
|
||||
<input
|
||||
v-model="shareOptions.password"
|
||||
@@ -50,19 +77,40 @@
|
||||
|
||||
<!--Set expiration-->
|
||||
<AppInputText v-if="isExpiration" class="-mt-2">
|
||||
<SelectBoxInput v-model="shareOptions.expiration" :data="$translateSelectOptions(expirationList)" class="box" />
|
||||
<SelectBoxInput
|
||||
v-model="shareOptions.expiration"
|
||||
:data="$translateSelectOptions(expirationList)"
|
||||
class="box"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
|
||||
<!--Send on emails switch-->
|
||||
<div>
|
||||
<AppInputSwitch :title="$t('popup.share.email_send')" :description="$t('popup.share.email_description')" :is-last="!isEmailSharing">
|
||||
<AppInputSwitch
|
||||
:title="$t('popup.share.email_send')"
|
||||
:description="$t('popup.share.email_description')"
|
||||
:is-last="!isEmailSharing"
|
||||
>
|
||||
<SwitchInput v-model="isEmailSharing" class="switch" :state="isEmailSharing" />
|
||||
</AppInputSwitch>
|
||||
|
||||
<!--Set expiration-->
|
||||
<ValidationProvider v-if="isEmailSharing" tag="div" mode="passive" name="Email" rules="required" v-slot="{ errors }" class="-mt-2">
|
||||
<MultiEmailInput rules="required" v-model="shareOptions.emails" :label="$t('shared_form.recipients_label')" :isError="errors[0]" />
|
||||
<ValidationProvider
|
||||
v-if="isEmailSharing"
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="Email"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
class="-mt-2"
|
||||
>
|
||||
<MultiEmailInput
|
||||
rules="required"
|
||||
v-model="shareOptions.emails"
|
||||
:label="$t('shared_form.recipients_label')"
|
||||
:isError="errors[0]"
|
||||
/>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</ValidationObserver>
|
||||
@@ -78,7 +126,13 @@
|
||||
<ButtonBase v-if="!isGeneratedShared" class="w-full" @click.native="$closePopup()" button-style="secondary">
|
||||
{{ $t('popup_move_item.cancel') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="submitShareOptions" button-style="theme" :loading="isLoading" :disabled="isLoading">
|
||||
<ButtonBase
|
||||
class="w-full"
|
||||
@click.native="submitShareOptions"
|
||||
button-style="theme"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
{{ submitButtonText }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
@@ -135,7 +189,9 @@ export default {
|
||||
computed: {
|
||||
...mapGetters(['permissionOptions', 'expirationList']),
|
||||
itemTypeTitle() {
|
||||
return this.pickedItem && this.pickedItem.data.type === 'folder' ? this.$t('types.folder') : this.$t('types.file')
|
||||
return this.pickedItem && this.pickedItem.data.type === 'folder'
|
||||
? this.$t('types.folder')
|
||||
: this.$t('types.file')
|
||||
},
|
||||
isFolder() {
|
||||
return this.pickedItem && this.pickedItem.data.type === 'folder'
|
||||
|
||||
@@ -31,7 +31,11 @@
|
||||
<ValidationObserver @submit.prevent v-slot="{ invalid }" ref="shareEmail" tag="form">
|
||||
<ValidationProvider tag="div" mode="passive" name="Email" rules="required" v-slot="{ errors }">
|
||||
<AppInputText title="Share with" :error="errors[0]" :is-last="true">
|
||||
<MultiEmailInput rules="required" v-model="emails" :label="$t('shared_form.label_send_to_recipients')" />
|
||||
<MultiEmailInput
|
||||
rules="required"
|
||||
v-model="emails"
|
||||
:label="$t('shared_form.label_send_to_recipients')"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
</ValidationObserver>
|
||||
@@ -41,7 +45,13 @@
|
||||
<ButtonBase class="w-full" @click.native="showSection(undefined)" button-style="secondary">
|
||||
{{ $t('Show Details') }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="sendViaEmail" button-style="theme" :loading="isLoading" :disabled="isLoading">
|
||||
<ButtonBase
|
||||
class="w-full"
|
||||
@click.native="sendViaEmail"
|
||||
button-style="theme"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
{{ $t('Send') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
@@ -60,7 +70,14 @@
|
||||
|
||||
<ValidationObserver @submit.prevent ref="shareForm" v-slot="{ invalid }" tag="form">
|
||||
<!--Permission Select-->
|
||||
<ValidationProvider v-if="isFolder" tag="div" mode="passive" name="Permission" rules="required" v-slot="{ errors }">
|
||||
<ValidationProvider
|
||||
v-if="isFolder"
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="Permission"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<AppInputText :title="$t('shared_form.label_permission')" :error="errors[0]">
|
||||
<SelectInput
|
||||
v-model="shareOptions.permission"
|
||||
@@ -74,12 +91,23 @@
|
||||
|
||||
<!--Password Switch-->
|
||||
<div>
|
||||
<AppInputSwitch :title="$t('shared_form.label_password_protection')" :description="$t('popup.share.password_description')">
|
||||
<SwitchInput v-model="shareOptions.isProtected" class="switch" :state="shareOptions.isProtected" />
|
||||
<AppInputSwitch
|
||||
:title="$t('shared_form.label_password_protection')"
|
||||
:description="$t('popup.share.password_description')"
|
||||
>
|
||||
<SwitchInput
|
||||
v-model="shareOptions.isProtected"
|
||||
class="switch"
|
||||
:state="shareOptions.isProtected"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<ActionButton
|
||||
v-if="pickedItem.data.relationships.shared.data.attributes.protected && canChangePassword && shareOptions.isProtected"
|
||||
v-if="
|
||||
pickedItem.data.relationships.shared.data.attributes.protected &&
|
||||
canChangePassword &&
|
||||
shareOptions.isProtected
|
||||
"
|
||||
@click.native="changePassword"
|
||||
class="mb-6 -mt-4"
|
||||
>
|
||||
@@ -87,7 +115,14 @@
|
||||
</ActionButton>
|
||||
|
||||
<!--Set password-->
|
||||
<ValidationProvider v-if="shareOptions.isProtected && !canChangePassword" tag="div" mode="passive" name="Password" rules="required" v-slot="{ errors }">
|
||||
<ValidationProvider
|
||||
v-if="shareOptions.isProtected && !canChangePassword"
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="Password"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<AppInputText :error="errors[0]" class="-mt-2">
|
||||
<input
|
||||
v-model="shareOptions.password"
|
||||
@@ -102,23 +137,48 @@
|
||||
|
||||
<!--Expiration switch-->
|
||||
<div>
|
||||
<AppInputSwitch :title="$t('expiration')" :description="$t('popup.share.expiration_description')" :is-last="!shareOptions.expiration">
|
||||
<SwitchInput v-model="shareOptions.expiration" class="switch" :state="shareOptions.expiration ? 1 : 0" />
|
||||
<AppInputSwitch
|
||||
:title="$t('expiration')"
|
||||
:description="$t('popup.share.expiration_description')"
|
||||
:is-last="!shareOptions.expiration"
|
||||
>
|
||||
<SwitchInput
|
||||
v-model="shareOptions.expiration"
|
||||
class="switch"
|
||||
:state="shareOptions.expiration ? 1 : 0"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<!--Set expiration-->
|
||||
<AppInputText v-if="shareOptions.expiration" class="-mt-2" :is-last="true">
|
||||
<SelectBoxInput v-model="shareOptions.expiration" :data="$translateSelectOptions(expirationList)" :value="shareOptions.expiration" class="box" />
|
||||
<SelectBoxInput
|
||||
v-model="shareOptions.expiration"
|
||||
:data="$translateSelectOptions(expirationList)"
|
||||
:value="shareOptions.expiration"
|
||||
class="box"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
</ValidationObserver>
|
||||
</PopupContent>
|
||||
|
||||
<PopupActions>
|
||||
<ButtonBase class="w-full" @click.native="destroySharing" :button-style="destroyButtonStyle" :loading="isDeleting" :disabled="isDeleting">
|
||||
<ButtonBase
|
||||
class="w-full"
|
||||
@click.native="destroySharing"
|
||||
:button-style="destroyButtonStyle"
|
||||
:loading="isDeleting"
|
||||
:disabled="isDeleting"
|
||||
>
|
||||
{{ destroyButtonText }}
|
||||
</ButtonBase>
|
||||
<ButtonBase class="w-full" @click.native="updateShareOptions" button-style="theme" :loading="isLoading" :disabled="isLoading">
|
||||
<ButtonBase
|
||||
class="w-full"
|
||||
@click.native="updateShareOptions"
|
||||
button-style="theme"
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
{{ $t('Store Changes') }}
|
||||
</ButtonBase>
|
||||
</PopupActions>
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="tab-wrapper">
|
||||
<div class="tab" :class="{ active: tab.isActive }" @click="selectTab(tab)" v-for="(tab, i) in tabs" :key="i">
|
||||
<div
|
||||
class="tab"
|
||||
:class="{ active: tab.isActive }"
|
||||
@click="selectTab(tab)"
|
||||
v-for="(tab, i) in tabs"
|
||||
:key="i"
|
||||
>
|
||||
<!--Icon-->
|
||||
<mail-icon v-if="tab.icon === 'email'" class="tab-icon text-theme dark-text-theme" size="17" />
|
||||
<link-icon v-if="tab.icon === 'link'" class="tab-icon text-theme dark-text-theme" size="17" />
|
||||
|
||||
@@ -55,7 +55,12 @@
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li v-for="(page, index) in data.meta.last_page" :key="index" class="inline-block p-1" @click="goToPage(page)">
|
||||
<li
|
||||
v-for="(page, index) in data.meta.last_page"
|
||||
:key="index"
|
||||
class="inline-block p-1"
|
||||
@click="goToPage(page)"
|
||||
>
|
||||
<a
|
||||
class="page-link"
|
||||
:class="{
|
||||
@@ -100,7 +105,13 @@
|
||||
<a class="page-link"> 1 </a>
|
||||
</li>
|
||||
|
||||
<li v-if="pageIndex < 5" v-for="(page, index) in 5" :key="index" class="inline-block p-1" @click="goToPage(page)">
|
||||
<li
|
||||
v-if="pageIndex < 5"
|
||||
v-for="(page, index) in 5"
|
||||
:key="index"
|
||||
class="inline-block p-1"
|
||||
@click="goToPage(page)"
|
||||
>
|
||||
<a
|
||||
class="page-link"
|
||||
:class="{
|
||||
@@ -116,7 +127,13 @@
|
||||
</li>
|
||||
|
||||
<!--Floated Pages-->
|
||||
<li v-if="pageIndex >= 5 && pageIndex < data.meta.last_page - 3" v-for="(page, index) in floatPages" :key="index" class="inline-block p-1" @click="goToPage(page)">
|
||||
<li
|
||||
v-if="pageIndex >= 5 && pageIndex < data.meta.last_page - 3"
|
||||
v-for="(page, index) in floatPages"
|
||||
:key="index"
|
||||
class="inline-block p-1"
|
||||
@click="goToPage(page)"
|
||||
>
|
||||
<a
|
||||
class="page-link"
|
||||
:class="{
|
||||
@@ -141,7 +158,8 @@
|
||||
<a
|
||||
class="page-link"
|
||||
:class="{
|
||||
'bg-light-background dark:bg-4x-dark-foreground dark:text-gray-300': pageIndex === data.meta.last_page - (4 - index),
|
||||
'bg-light-background dark:bg-4x-dark-foreground dark:text-gray-300':
|
||||
pageIndex === data.meta.last_page - (4 - index),
|
||||
}"
|
||||
>
|
||||
{{ data.meta.last_page - (4 - index) }}
|
||||
@@ -149,7 +167,11 @@
|
||||
</li>
|
||||
|
||||
<!--Show last page-->
|
||||
<li class="inline-block p-1" v-if="pageIndex < data.meta.last_page - 3" @click="goToPage(data.meta.last_page)">
|
||||
<li
|
||||
class="inline-block p-1"
|
||||
v-if="pageIndex < data.meta.last_page - 3"
|
||||
@click="goToPage(data.meta.last_page)"
|
||||
>
|
||||
<a class="page-link">
|
||||
{{ data.meta.last_page }}
|
||||
</a>
|
||||
@@ -169,7 +191,9 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<span class="text-xs text-gray-600 dark:text-gray-500"> Showing {{ data.meta.from }} - {{ data.meta.to }} from {{ data.meta.total }} records </span>
|
||||
<span class="text-xs text-gray-600 dark:text-gray-500">
|
||||
Showing {{ data.meta.from }} - {{ data.meta.to }} from {{ data.meta.total }} records
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -239,7 +263,14 @@ export default {
|
||||
if (this.paginator) this.URI = this.URI + '?page=' + page
|
||||
|
||||
// Add filder URI if is defined sorting
|
||||
if (this.filter.field) this.URI = this.URI + (this.paginator ? '&' : '?') + 'sort=' + this.filter.field + '&direction=' + this.filter.sort
|
||||
if (this.filter.field)
|
||||
this.URI =
|
||||
this.URI +
|
||||
(this.paginator ? '&' : '?') +
|
||||
'sort=' +
|
||||
this.filter.field +
|
||||
'&direction=' +
|
||||
this.filter.sort
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
|
||||
@@ -3,16 +3,30 @@
|
||||
<!--Item thumbnail-->
|
||||
<div class="relative w-16">
|
||||
<!--Member thumbnail for team folders-->
|
||||
<MemberAvatar v-if="user && canShowAuthor" :size="28" :is-border="true" :member="item.data.relationships.owner" class="absolute right-1.5 -bottom-2 z-10" />
|
||||
<MemberAvatar
|
||||
v-if="user && canShowAuthor"
|
||||
:size="28"
|
||||
:is-border="true"
|
||||
:member="item.data.relationships.owner"
|
||||
class="absolute right-1.5 -bottom-2 z-10"
|
||||
/>
|
||||
|
||||
<!--Emoji Icon-->
|
||||
<Emoji v-if="item.data.attributes.emoji" :emoji="item.data.attributes.emoji" class="ml-1 scale-110 transform text-5xl" />
|
||||
<Emoji
|
||||
v-if="item.data.attributes.emoji"
|
||||
:emoji="item.data.attributes.emoji"
|
||||
class="ml-1 scale-110 transform text-5xl"
|
||||
/>
|
||||
|
||||
<!--Folder Icon-->
|
||||
<FolderIcon v-if="isFolder && !item.data.attributes.emoji" :item="item" />
|
||||
|
||||
<!--File Icon-->
|
||||
<FileIconThumbnail v-if="isFile || isVideo || isAudio || (isImage && !item.data.attributes.thumbnail)" :item="item" class="pr-2" />
|
||||
<FileIconThumbnail
|
||||
v-if="isFile || isVideo || isAudio || (isImage && !item.data.attributes.thumbnail)"
|
||||
:item="item"
|
||||
class="pr-2"
|
||||
/>
|
||||
|
||||
<!--Image thumbnail-->
|
||||
<img
|
||||
@@ -27,7 +41,10 @@
|
||||
<!--Item Info-->
|
||||
<div class="pl-2">
|
||||
<!--Item Title-->
|
||||
<b class="mb-0.5 block overflow-hidden text-ellipsis whitespace-nowrap text-sm hover:underline" style="max-width: 240px">
|
||||
<b
|
||||
class="mb-0.5 block overflow-hidden text-ellipsis whitespace-nowrap text-sm hover:underline"
|
||||
style="max-width: 240px"
|
||||
>
|
||||
{{ item.data.attributes.name }}
|
||||
</b>
|
||||
|
||||
@@ -39,11 +56,14 @@
|
||||
</div>
|
||||
|
||||
<!--File & Image sub line-->
|
||||
<small v-if="!isFolder" class="block text-xs text-gray-500"> {{ item.data.attributes.filesize }}, {{ timeStamp }} </small>
|
||||
<small v-if="!isFolder" class="block text-xs text-gray-500">
|
||||
{{ item.data.attributes.filesize }}, {{ timeStamp }}
|
||||
</small>
|
||||
|
||||
<!--Folder sub line-->
|
||||
<small v-if="isFolder" class="block text-xs text-gray-500">
|
||||
{{ folderItems === 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }}, {{ timeStamp }}
|
||||
{{ folderItems === 0 ? $t('folder.empty') : $tc('folder.item_counts', folderItems) }},
|
||||
{{ timeStamp }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
@@ -105,7 +125,9 @@ export default {
|
||||
)
|
||||
},
|
||||
folderItems() {
|
||||
return this.item.data.attributes.deleted_at ? this.item.data.attributes.trashed_items : this.item.data.attributes.items
|
||||
return this.item.data.attributes.deleted_at
|
||||
? this.item.data.attributes.trashed_items
|
||||
: this.item.data.attributes.items
|
||||
},
|
||||
canShowAuthor() {
|
||||
return !this.isFolder && this.user.data.id !== this.item.data.relationships.owner.data.id
|
||||
|
||||
@@ -24,10 +24,30 @@
|
||||
</span>
|
||||
|
||||
<!--Item icon-->
|
||||
<hard-drive-icon v-if="['public', 'files'].includes(nodes.location)" size="17" class="icon vue-feather" :class="{ 'text-theme dark-text-theme': isSelectedItem }" />
|
||||
<users-icon v-if="nodes.location === 'team-folders'" size="17" class="icon vue-feather" :class="{ 'text-theme dark-text-theme': isSelectedItem }" />
|
||||
<user-plus-icon v-if="nodes.location === 'shared-with-me'" size="17" class="icon vue-feather" :class="{ 'text-theme dark-text-theme': isSelectedItem }" />
|
||||
<folder-icon v-if="!nodes.location" size="17" class="icon vue-feather" :class="{ 'text-theme dark-text-theme': isSelectedItem }" />
|
||||
<hard-drive-icon
|
||||
v-if="['public', 'files'].includes(nodes.location)"
|
||||
size="17"
|
||||
class="icon vue-feather"
|
||||
:class="{ 'text-theme dark-text-theme': isSelectedItem }"
|
||||
/>
|
||||
<users-icon
|
||||
v-if="nodes.location === 'team-folders'"
|
||||
size="17"
|
||||
class="icon vue-feather"
|
||||
:class="{ 'text-theme dark-text-theme': isSelectedItem }"
|
||||
/>
|
||||
<user-plus-icon
|
||||
v-if="nodes.location === 'shared-with-me'"
|
||||
size="17"
|
||||
class="icon vue-feather"
|
||||
:class="{ 'text-theme dark-text-theme': isSelectedItem }"
|
||||
/>
|
||||
<folder-icon
|
||||
v-if="!nodes.location"
|
||||
size="17"
|
||||
class="icon vue-feather"
|
||||
:class="{ 'text-theme dark-text-theme': isSelectedItem }"
|
||||
/>
|
||||
|
||||
<!--Item label-->
|
||||
<b
|
||||
@@ -40,7 +60,14 @@
|
||||
</div>
|
||||
|
||||
<!--Children-->
|
||||
<tree-node :disabled-by-id="disabledById" :depth="depth + 1" v-if="isVisible" :nodes="item" v-for="item in nodes.folders" :key="item.id" />
|
||||
<tree-node
|
||||
:disabled-by-id="disabledById"
|
||||
:depth="depth + 1"
|
||||
v-if="isVisible"
|
||||
:nodes="item"
|
||||
v-for="item in nodes.folders"
|
||||
:key="item.id"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -23,11 +23,21 @@
|
||||
/>
|
||||
</div>
|
||||
<folder-icon size="17" class="vue-feather mr-2.5" :class="{ 'text-theme': isSelected }" />
|
||||
<b class="max-w-1 overflow-hidden text-ellipsis whitespace-nowrap text-xs font-bold" :class="{ 'text-theme': isSelected }">
|
||||
<b
|
||||
class="max-w-1 overflow-hidden text-ellipsis whitespace-nowrap text-xs font-bold"
|
||||
:class="{ 'text-theme': isSelected }"
|
||||
>
|
||||
{{ nodes.name }}
|
||||
</b>
|
||||
</div>
|
||||
<tree-node :disabled="disableChildren" :depth="depth + 1" v-if="isVisible" :nodes="item" v-for="item in nodes.folders" :key="item.id" />
|
||||
<tree-node
|
||||
:disabled="disableChildren"
|
||||
:depth="depth + 1"
|
||||
v-if="isVisible"
|
||||
:nodes="item"
|
||||
v-for="item in nodes.folders"
|
||||
:key="item.id"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<transition name="vignette">
|
||||
<div v-if="isVisible" class="vignette bg-dark-background bg-opacity-[0.35] dark:bg-opacity-[0.45]" @click="closePopup"></div>
|
||||
<div
|
||||
v-if="isVisible"
|
||||
class="vignette bg-dark-background bg-opacity-[0.35] dark:bg-opacity-[0.45]"
|
||||
@click="closePopup"
|
||||
></div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user