Merge remote-tracking branch 'origin/version-1.8.3' into v2

# Conflicts:
#	app/FileManagerFolder.php
#	app/Http/Controllers/AppFunctionsController.php
#	app/Http/Controllers/Auth/AuthController.php
#	app/Http/Controllers/FileManager/BrowseController.php
#	app/Http/Controllers/General/SetupWizardController.php
#	app/Http/Controllers/General/UpgradeAppController.php
#	app/Http/Controllers/Sharing/FileSharingController.php
#	app/Http/helpers.php
#	app/Setting.php
#	composer.lock
#	public/mix-manifest.json
#	resources/js/App.vue
#	resources/js/components/Others/Forms/FormLabel.vue
#	resources/js/store/modules/app.js
#	resources/js/views/Admin.vue
#	resources/js/views/Mobile/AdminMobileMenu.vue
#	resources/js/views/Shared/SharedPage.vue
#	resources/views/index.blade.php
#	resources/views/vuefilemanager/crawler/og-view.blade.php
#	resources/views/vuefilemanager/invoice.blade.php
#	routes/api.php
#	routes/web.php
This commit is contained in:
Peter Papp
2021-03-27 12:12:42 +01:00
39 changed files with 3404 additions and 132 deletions
@@ -17,6 +17,7 @@
<cloud-icon v-if="link.icon === 'cloud'" size="17"></cloud-icon>
<monitor-icon v-if="link.icon === 'monitor'" size="17"></monitor-icon>
<box-icon v-if="link.icon === 'box'" size="17"></box-icon>
<globe-icon v-if="link.icon === 'language'" size="17"></globe-icon>
</div>
<b class="menu-link">
<span>{{ link.title }}</span>
@@ -39,6 +40,7 @@
Trash2Icon,
CloudIcon,
PowerIcon,
GlobeIcon,
ShareIcon,
UsersIcon,
UserIcon,
@@ -61,6 +63,7 @@
Trash2Icon,
CloudIcon,
PowerIcon,
GlobeIcon,
UsersIcon,
ShareIcon,
LockIcon,
@@ -0,0 +1,867 @@
<template>
<PopupWrapper name="create-language">
<!--Title-->
<PopupHeader :title="'Create Language'" icon="edit" />
<!--Content-->
<PopupContent>
<!--Form to set sharing-->
<ValidationObserver @submit.prevent="createFolder" ref="createForm" v-slot="{ invalid }" tag="form" class="form-wrapper">
<!--Set password-->
<ValidationProvider tag="div" mode="passive" class="input-wrapper password" name="Language Name" rules="required" v-slot="{ errors }">
<label class="input-label">Type Name:</label>
<input v-model="name" :class="{'is-error': errors[0]}" type="text" ref="input" placeholder="Type Language Name">
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<!--Set password-->
<ValidationProvider tag="div" mode="passive" class="input-wrapper password" name="Language Locale" rules="required" v-slot="{ errors }">
<label class="input-label">Select Locale:</label>
<SelectInput v-model="locale" :options="allLocals" placeholder="Select Language Locale" :isError="errors[0]"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</ValidationObserver>
</PopupContent>
<!--Actions-->
<PopupActions>
<ButtonBase
class="popup-button"
@click.native="$closePopup()"
button-style="secondary"
>Cancel
</ButtonBase>
<ButtonBase
class="popup-button"
@click.native="createLanguage"
button-style="theme"
:loading="isLoading"
:disabled="isLoading"
>Create Language
</ButtonBase>
</PopupActions>
</PopupWrapper>
</template>
<script>
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
import PopupWrapper from '@/components/Others/Popup/PopupWrapper'
import PopupActions from '@/components/Others/Popup/PopupActions'
import PopupContent from '@/components/Others/Popup/PopupContent'
import PopupHeader from '@/components/Others/Popup/PopupHeader'
import SelectInput from '@/components/Others/Forms/SelectInput'
import ButtonBase from '@/components/FilesView/ButtonBase'
import {required} from 'vee-validate/dist/rules'
import {events} from '@/bus'
import axios from 'axios'
export default {
name: 'CreateLanguage',
components: {
ValidationProvider,
ValidationObserver,
PopupWrapper,
PopupActions,
PopupContent,
PopupHeader,
SelectInput,
ButtonBase,
required,
},
data() {
return {
name: undefined,
locale: undefined,
isLoading: false,
allLocals: [
{
value: "ab",
label: "Abkhaz"
},
{
value: "aa",
label: "Afar"
},
{
value: "af",
label: "Afrikaans"
},
{
value: "ak",
label: "Akan"
},
{
value: "sq",
label: "Albanian"
},
{
value: "am",
label: "Amharic"
},
{
value: "ar",
label: "Arabic"
},
{
value: "an",
label: "Aragonese"
},
{
value: "hy",
label: "Armenian"
},
{
value: "as",
label: "Assamese"
},
{
value: "av",
label: "Avaric"
},
{
value: "ae",
label: "Avestan"
},
{
value: "ay",
label: "Aymara"
},
{
value: "az",
label: "Azerbaijani"
},
{
value: "bm",
label: "Bambara"
},
{
value: "ba",
label: "Bashkir"
},
{
value: "eu",
label: "Basque"
},
{
value: "be",
label: "Belarusian"
},
{
value: "bn",
label: "Bengali; Bangla"
},
{
value: "bh",
label: "Bihari"
},
{
value: "bi",
label: "Bislama"
},
{
value: "bs",
label: "Bosnian"
},
{
value: "br",
label: "Breton"
},
{
value: "bg",
label: "Bulgarian"
},
{
value: "my",
label: "Burmese"
},
{
value: "ca",
label: "Catalan; Valencian"
},
{
value: "ch",
label: "Chamorro"
},
{
value: "ce",
label: "Chechen"
},
{
value: "ny",
label: "Chichewa; Chewa; Nyanja"
},
{
value: "zh",
label: "Chinese"
},
{
value: "cv",
label: "Chuvash"
},
{
value: "kw",
label: "Cornish"
},
{
value: "co",
label: "Corsican"
},
{
value: "cr",
label: "Cree"
},
{
value: "hr",
label: "Croatian"
},
{
value: "cs",
label: "Czech"
},
{
value: "da",
label: "Danish"
},
{
value: "dv",
label: "Divehi; Dhivehi; Maldivian;"
},
{
value: "nl",
label: "Dutch"
},
{
value: "dz",
label: "Dzongkha"
},
{
value: "en",
label: "English"
},
{
value: "eo",
label: "Esperanto"
},
{
value: "et",
label: "Estonian"
},
{
value: "ee",
label: "Ewe"
},
{
value: "fo",
label: "Faroese"
},
{
value: "fj",
label: "Fijian"
},
{
value: "fi",
label: "Finnish"
},
{
value: "fr",
label: "French"
},
{
value: "ff",
label: "Fula; Fulah; Pulaar; Pular"
},
{
value: "gl",
label: "Galician"
},
{
value: "lg",
label: "Ganda"
},
{
value: "ka",
label: "Georgian"
},
{
value: "de",
label: "German"
},
{
value: "el",
label: "Greek, Modern"
},
{
value: "gn",
label: "Guaraní"
},
{
value: "gu",
label: "Gujarati"
},
{
value: "ht",
label: "Haitian; Haitian Creole"
},
{
value: "ha",
label: "Hausa"
},
{
value: "he",
label: "Hebrew (modern)"
},
{
value: "hz",
label: "Herero"
},
{
value: "hi",
label: "Hindi"
},
{
value: "ho",
label: "Hiri Motu"
},
{
value: "hu",
label: "Hungarian"
},
{
value: "ia",
label: "Interlingua"
},
{
value: "id",
label: "Indonesian"
},
{
value: "ie",
label: "Interlingue"
},
{
value: "ga",
label: "Irish"
},
{
value: "ig",
label: "Igbo"
},
{
value: "ik",
label: "Inupiaq"
},
{
value: "io",
label: "Ido"
},
{
value: "is",
label: "Icelandic"
},
{
value: "it",
label: "Italian"
},
{
value: "iu",
label: "Inuktitut"
},
{
value: "ja",
label: "Japanese"
},
{
value: "jv",
label: "Javanese"
},
{
value: "kl",
label: "Kalaallisut, Greenlandic"
},
{
value: "kn",
label: "Kannada"
},
{
value: "kr",
label: "Kanuri"
},
{
value: "ks",
label: "Kashmiri"
},
{
value: "kk",
label: "Kazakh"
},
{
value: "km",
label: "Khmer"
},
{
value: "ki",
label: "Kikuyu, Gikuyu"
},
{
value: "rw",
label: "Kinyarwanda"
},
{
value: "rn",
label: "Kirundi"
},
{
value: "ky",
label: "Kyrgyz"
},
{
value: "kv",
label: "Komi"
},
{
value: "kg",
label: "Kongo"
},
{
value: "ko",
label: "Korean"
},
{
value: "ku",
label: "Kurdish"
},
{
value: "kj",
label: "Kwanyama, Kuanyama"
},
{
value: "la",
label: "Latin"
},
{
value: "lb",
label: "Luxembourgish, Letzeburgesch"
},
{
value: "li",
label: "Limburgish, Limburgan, Limburger"
},
{
value: "ln",
label: "Lingala"
},
{
value: "lo",
label: "Lao"
},
{
value: "lt",
label: "Lithuanian"
},
{
value: "lu",
label: "Luba-Katanga"
},
{
value: "lv",
label: "Latvian"
},
{
value: "gv",
label: "Manx"
},
{
value: "mk",
label: "Macedonian"
},
{
value: "mg",
label: "Malagasy"
},
{
value: "ms",
label: "Malay"
},
{
value: "ml",
label: "Malayalam"
},
{
value: "mt",
label: "Maltese"
},
{
value: "mi",
label: "MÄori"
},
{
value: "mr",
label: "Marathi"
},
{
value: "mh",
label: "Marshallese"
},
{
value: "mn",
label: "Mongolian"
},
{
value: "na",
label: "Nauru"
},
{
value: "nv",
label: "Navajo, Navaho"
},
{
value: "nb",
label: "Norwegian"
},
{
value: "nd",
label: "North Ndebele"
},
{
value: "ne",
label: "Nepali"
},
{
value: "ng",
label: "Ndonga"
},
{
value: "nn",
label: "Norwegian Nynorsk"
},
{
value: "no",
label: "Norwegian"
},
{
value: "ii",
label: "Nuosu"
},
{
value: "oc",
label: "Occitan"
},
{
value: "oj",
label: "Ojibwe, Ojibwa"
},
{
value: "cu",
label: "Old Church Slavonic, Church Slavic, Church Slavonic, Old Bulgarian, Old Slavonic"
},
{
value: "om",
label: "Oromo"
},
{
value: "or",
label: "Oriya"
},
{
value: "os",
label: "Ossetian, Ossetic"
},
{
value: "pa",
label: "Panjabi, Punjabi"
},
{
value: "pi",
label: "Pali"
},
{
value: "fa",
label: "Persian (Farsi)"
},
{
value: "pl",
label: "Polish"
},
{
value: "ps",
label: "Pashto, Pushto"
},
{
value: "pt",
label: "Portuguese"
},
{
value: "qu",
label: "Quechua"
},
{
value: "rm",
label: "Romansh"
},
{
value: "ro",
label: "Romanian"
},
{
value: "ru",
label: "Russian"
},
{
value: "sa",
label: "Sanskrit"
},
{
value: "sc",
label: "Sardinian"
},
{
value: "sd",
label: "Sindhi"
},
{
value: "se",
label: "Northern Sami"
},
{
value: "sm",
label: "Samoan"
},
{
value: "sg",
label: "Sango"
},
{
value: "sr",
label: "Serbian"
},
{
value: "gd",
label: "Scottish Gaelic"
},
{
value: "sn",
label: "Shona"
},
{
value: "si",
label: "Sinhala, Sinhalese"
},
{
value: "sk",
label: "Slovak"
},
{
value: "sl",
label: "Slovene"
},
{
value: "so",
label: "Somali"
},
{
value: "st",
label: "Southern Sotho"
},
{
value: "az",
label: "South Azerbaijani"
},
{
value: "nr",
label: "South Ndebele"
},
{
value: "es",
label: "Spanish; Castilian"
},
{
value: "su",
label: "Sundanese"
},
{
value: "sw",
label: "Swahili"
},
{
value: "ss",
label: "Swati"
},
{
value: "sv",
label: "Swedish"
},
{
value: "ta",
label: "Tamil"
},
{
value: "te",
label: "Telugu"
},
{
value: "tg",
label: "Tajik"
},
{
value: "th",
label: "Thai"
},
{
value: "ti",
label: "Tigrinya"
},
{
value: "bo",
label: "Tibetan Standard, Tibetan, Central"
},
{
value: "tk",
label: "Turkmen"
},
{
value: "tl",
label: "Tagalog"
},
{
value: "tn",
label: "Tswana"
},
{
value: "to",
label: "Tonga (Tonga Islands)"
},
{
value: "tr",
label: "Turkish"
},
{
value: "ts",
label: "Tsonga"
},
{
value: "tt",
label: "Tatar"
},
{
value: "tw",
label: "Twi"
},
{
value: "ty",
label: "Tahitian"
},
{
value: "ug",
label: "Uyghur, Uighur"
},
{
value: "uk",
label: "Ukrainian"
},
{
value: "ur",
label: "Urdu"
},
{
value: "uz",
label: "Uzbek"
},
{
value: "ve",
label: "Venda"
},
{
value: "vi",
label: "Vielabele"
},
{
value: "vo",
label: "Volapük"
},
{
value: "wa",
label: "Walloon"
},
{
value: "cy",
label: "Welsh"
},
{
value: "wo",
label: "Wolof"
},
{
value: "fy",
label: "Western Frisian"
},
{
value: "xh",
label: "Xhosa"
},
{
value: "yi",
label: "Yiddish"
},
{
value: "yo",
label: "Yoruba"
},
{
value: "za",
label: "Zhuang, Chuang"
},
{
value: "zu",
label: "Zulu"
}
]
}
},
methods: {
async createLanguage() {
// Validate fields
const isValid = await this.$refs.createForm.validate();
if (isValid) {
this.isLoading = true
axios.post('/api/languages', {
name: this.name,
locale: this.locale
})
.then((response) => {
events.$emit('add-language', response.data)
})
.catch(() => Vue.prototype.$isSomethingWrong())
.finally(() => {
this.name = undefined
this.locale = undefined
this.isLoading = false
this.$closePopup()
})
}
},
},
mounted () {
this.name = undefined,
this.locale = undefined
}
}
</script>
<style scoped lang="scss">
@import "@assets/vue-file-manager/_inapp-forms.scss";
@import '@assets/vue-file-manager/_forms';
.item-thumbnail {
margin-bottom: 20px;
}
</style>
@@ -1,6 +1,7 @@
<template>
<div class="form-label">
<edit-2-icon size="22" class="icon text-theme" />
<edit-2-icon v-if="!icon" size="22" class="icon text-theme" />
<settings-icon v-if="icon === 'settings'" size="22" class="icon text-theme" />
<b class="label">
<slot></slot>
</b>
@@ -8,12 +9,14 @@
</template>
<script>
import { Edit2Icon } from 'vue-feather-icons'
import { Edit2Icon, SettingsIcon } from 'vue-feather-icons'
export default {
name: 'FormLabel',
props: ['icon'],
components: {
Edit2Icon
Edit2Icon,
SettingsIcon
}
}
</script>
@@ -30,7 +33,7 @@
.icon {
margin-right: 10px;
path {
path, circle {
color: inherit;
}
}
+23
View File
@@ -23,6 +23,29 @@ const Helpers = {
})
}, 150)
Vue.prototype.$loadLanguage = function (language) {
return new Promise((resolve, reject) => {
let locale = language ? language : this.$store.getters.config.language
axios.get(`/language/${locale}`)
.then((response) => {
let lang = response.data.language_strings
let obj = {}
lang.map(element => {
obj[element.key] = element.value
})
i18n.setLocaleMessage(locale, obj)
i18n.locale = locale
resolve(true)
})
})
}
Vue.prototype.$updateImage = function (route, name, image) {
// Create form
+3 -4
View File
@@ -8,10 +8,9 @@ import cn from './lang/cn.json'
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: config.locale,
messages: Object.assign({
en
}),
locale: config.language,
silentTranslationWarn: true,
});
export default i18n;
+4 -2
View File
@@ -25,7 +25,8 @@
"pages": "Pages",
"plans": "Plans",
"settings": "Settings",
"users": "Users"
"users": "Users",
"language": "Language"
},
"admin_page_dashboard": {
"backer_button": "Help Us Improve",
@@ -672,7 +673,8 @@
"users_list": "User Management",
"users_password": "Password",
"users_storage_usage": "Storage Usage",
"users_user": "User"
"users_user": "User",
"language": "Language"
},
"rows": {
"card": {
+10
View File
@@ -285,6 +285,16 @@ const routesAdmin = [
},
]
},
{
name: 'Language',
path: '/admin/language',
component: () =>
import(/* webpackChunkName: "chunks/app-language" */ './views/Admin/Languages/Language'),
meta: {
requiresAuth: true,
title: i18n.t('routes_title.language')
},
}
]
},
{
+10 -1
View File
@@ -41,6 +41,14 @@
{{ $t('admin_menu.pages') }}
</div>
</router-link>
<router-link :to="{name: 'Language'}" class="menu-list-item link">
<div class="icon text-theme">
<globe-icon size="17" />
</div>
<div class="label text-theme">
{{ $t('admin_menu.language') }}
</div>
</router-link>
</div>
</ContentGroup>
@@ -72,7 +80,7 @@
</template>
<script>
import { UsersIcon, SettingsIcon, FileTextIcon, CreditCardIcon, DatabaseIcon, BoxIcon, MonitorIcon } from 'vue-feather-icons'
import { UsersIcon, SettingsIcon, FileTextIcon, CreditCardIcon, DatabaseIcon, BoxIcon, MonitorIcon, GlobeIcon } from 'vue-feather-icons'
import ContentSidebar from '@/components/Sidebar/ContentSidebar'
import ContentGroup from '@/components/Sidebar/ContentGroup'
import MenuBar from '@/components/Sidebar/MenuBar'
@@ -94,6 +102,7 @@
UsersIcon,
MenuBar,
BoxIcon,
GlobeIcon
},
}
</script>
@@ -0,0 +1,262 @@
<template>
<div id="single-page">
<div id="page-content">
<MobileHeader :title="$router.currentRoute.meta.title"/>
<div class="wrapper">
<Spinner v-if="! loadedLanguages"/>
<div v-if="loadedLanguages" class="side-content">
<PageHeader :can-back="true" :title="$router.currentRoute.meta.title"/>
<div class="languages-wrapper page-tab from-fixed-width">
<div class="language-label-wrapper">
<label class="language-label">Languages</label>
</div>
<!-- Languages -->
<div class="all-language-wrapper">
<div @click="openLanguage(language)" v-for="language in languages" :key="language.id">
<div class="language" >
<label class="name" :class="{'active' :activeLanguage.locale === language.locale}">
{{language.name}}
</label>
<x-icon v-if="language.locale !== 'en' && language.locale !== setLanguage"
@click.stop="deleteLanguageConfirm(language)"
class="icon" size="17"/>
</div>
</div>
</div>
</div>
<MobileActionButton @click.native="createLanguage" icon="plus" class="button-add-language">
Add Language
</MobileActionButton>
</div>
<!-- Strings -->
<LanguageStrings :active-language="activeLanguage" :set-language="setLanguage" />
</div>
</div>
</div>
</template>
<script>
import LanguageStrings from '@/views/Admin/Languages/LanguageStrings'
import MobileHeader from '@/components/Mobile/MobileHeader'
import ButtonBase from '@/components/FilesView/ButtonBase'
import MobileActionButton from '@/components/FilesView/MobileActionButton'
import PageHeader from '@/components/Others/PageHeader'
import Spinner from '@/components/FilesView/Spinner'
import { PlusIcon, XIcon } from 'vue-feather-icons'
import { events } from '@/bus'
export default {
name: 'Language',
components: {
MobileActionButton,
LanguageStrings,
MobileHeader,
ButtonBase,
PageHeader,
PlusIcon,
Spinner,
XIcon
},
data () {
return {
activeLanguage: undefined,
languagesStrings:undefined,
setLanguage: undefined,
languages:undefined,
loadedLanguages: false,
}
},
methods: {
deleteLanguageConfirm(language) {
events.$emit('confirm:open', {
title: `Delete ${language.name} language?`,
message: 'Your language will be permanently deleted.',
buttonColor: 'danger-solid',
action: language
})
},
deleteLanguage(language) {
axios.delete(`/api/languages/${language.id}`)
.then(() => { this.getLanguages() })
},
createLanguage() {
events.$emit('popup:open', {name: 'create-language'})
},
getLanguages() {
this.loadedStrings = false
axios
.get('/api/languages')
.then((response) => {
this.languages = response.data.languages
this.activeLanguage = response.data.languages[0]
this.setLanguage = response.data.set_language
})
.catch(() => Vue.prototype.$isSomethingWrong())
.finally(() => {
this.loadedLanguages = true
})
},
openLanguage(language) {
this.activeLanguage = language
}
},
mounted () {
this.getLanguages()
events.$on('add-language', () => {
this.getLanguages()
})
events.$on('action:confirmed', language => {
this.deleteLanguage(language)
})
events.$on('language-name:update', (language) => {
let index = _.findIndex(this.languages, function(item) { return item.id === language.id })
this.languages[index].name = language.name
})
events.$on('language:set-as-default', (locale) => {
this.setLanguage = locale
})
},
destroyed () {
events.$off('action:confirmed')
},
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
#single-page {
height: 100%;
#page-content {
height: 100%;
}
}
.wrapper {
display: flex;
height: 100%;
}
.side-content{
flex: 0 0 225px;
.button-add-language {
margin-top: 30px;
/deep/.content {
display: flex;
align-items: center;
@include font-size(14);
font-weight: 700;
.icon {
margin-right: 10px;
}
}
}
.languages-wrapper {
margin-top: 70px;
.language-label-wrapper {
margin-bottom: 5px;
.language-label {
color: $light_text;
font-weight: 700;
@include font-size(12);
margin-top: 20px;
}
}
.all-language-wrapper {
.language {
display: flex;
align-items: center;
padding: 12px 25px 12px 0px;
cursor: pointer;
&:hover {
.icon {
display: block;
}
.name {
color: $theme !important;
}
}
.name {
color: $text;
font-weight: 700;
@include font-size(13);
cursor: pointer;
}
.icon {
display: none;
margin-left: auto;
cursor: pointer;
}
.active {
color: $theme !important;
}
}
}
}
}
@media only screen and (max-width: 1024px) {
.wrapper {
flex-direction: column;
.side-content{
margin-bottom: 70px;
}
.languages-wrapper {
margin-top: 0px;
}
}
}
@media only screen and (max-width: 690px) {
.side-content{
margin-bottom: 35px !important;
flex: none;
}
}
@media (prefers-color-scheme: dark) {
.language{
.name {
color: $dark_mode_text_primary !important;
}
}
.language-label {
color: $dark_mode_text_secondary !important;
}
}
</style>
@@ -0,0 +1,397 @@
<template>
<!-- Serach bar -->
<div v-if="strings" class="language-strings-wrapper form">
<div class="search-bar-wrapper">
<div class="search-bar">
<div v-if="!searchInput" class="icon" >
<search-icon size="19"></search-icon>
</div>
<div @click="resetInput" v-if="searchInput" class="icon">
<x-icon class="pointer" size="19"></x-icon>
</div>
<input
v-model="searchInput"
@input="searchStrings"
class="query"
type="text"
name="searchInput"
placeholder="Search Language Strings..."
/>
</div>
</div>
<Spinner v-if="!loadedStrings"/>
<!-- Set Language as default switch -->
<div v-if="loadedStrings" class="form block-form">
<FormLabel class="mt-70" icon="settings">Language Settings</FormLabel>
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">
Set as Default Language:
</label>
</div>
<SwitchInput
@input="updateLanguageSetting"
class="switch"
:class="{'disable-switch': languageSettingHandle }"
:state="languageSettingHandle"
/>
</div>
</div>
</div>
<!-- Language name -->
<div class="block-wrapper">
<label> Language Name:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Language Name" rules="required" v-slot="{ errors }">
<input type="text"
v-model="language.name"
@input="updateName"
:class="{'is-error': errors[0]}"
/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<!-- Strings -->
<FormLabel class="mt-70">Language Strings</FormLabel>
<div v-if="!loadSearch || filteredStrings.length === 0 && !searchInput" class="spinner-wrapper">
<Spinner class="spinner" />
</div>
<div v-if="loadSearch && filteredStrings.length > 0">
<div class="block-wrapper string" v-for="(string,index) in filteredStrings" :key="index">
<label> {{string.value}}:</label>
<ValidationProvider tag="div" class="input-wrapper" name="Language string" rules="required" v-slot="{ errors }">
<input type="text"
:class="{'is-error': errors[0]}"
@input="updateString(string.key)"
v-model="strings[getIndex(string.key)].value"
/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
</div>
<!-- Not Fount -->
<div class="not-found-wrapper" v-if="loadSearch && filteredStrings.length === 0 && searchInput">
<span class="not-found">Not Found</span>
</div>
</div>
</div>
</template>
<script>
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import FormLabel from '@/components/Others/Forms/FormLabel'
import { SearchIcon, XIcon } from 'vue-feather-icons'
import Spinner from '@/components/FilesView/Spinner'
import { events } from '@/bus'
import lodash from 'lodash'
export default {
name: 'LanguageStrings',
props: [ 'activeLanguage', 'setLanguage' ],
components: {
ValidationProvider,
ValidationObserver,
SwitchInput,
SearchIcon,
FormLabel,
Spinner,
XIcon,
},
computed: {
languageSettingHandle() {
return this.language.locale == this.setLanguage ? true : false
},
},
data () {
return {
defaultStrings: [],
filteredStrings: [],
loadSearch: false,
loadedStrings: false,
strings: undefined,
language: undefined,
searchInput: '',
}
},
watch: {
activeLanguage () {
this.getLanguageStrings(this.activeLanguage)
this.searchInput = ''
}
},
methods: {
updateLanguageSetting() {
this.$updateText('/settings', 'language', this.language.locale)
events.$emit('language:set-as-default', this.language.locale)
this.$loadLanguage(this.language.locale)
},
resetInput(){
this.searchInput = ''
this.searchStrings()
},
getIndex(key){
if(this.strings)
return _.findIndex(this.strings, function(string) { return string.key === key })
},
updateName() {
this.$updateText(`/languages/${this.language.id}`, 'name', this.language.name)
events.$emit('language-name:update', this.language)
},
updateString (key) {
// Return if the input is empty
if(! this.strings[this.getIndex(key)].value) return
this.$updateText(
`/languages/${this.language.id}/string`, `${key}`, this.strings[this.getIndex(key)].value,
)
},
searchStrings() {
this.loadSearch = false
this.filteredStrings = []
this.filterStrings()
},
filterStrings: _.debounce(function () {
this.filteredStrings = this.defaultStrings.filter(string => string.value.toLowerCase().includes( this.searchInput.toLowerCase() ))
this.loadSearch = true
}, 200),
getLanguageStrings (language) {
this.loadedStrings = false
this.defaultStrings = []
this.filteredStrings= []
axios
.get(`/api/languages/${language.id}/strings`)
.then(response => {
this.strings = response.data.translated_strings.language_strings
this.language = {
'id': response.data.translated_strings.id,
'name': response.data.translated_strings.name,
'locale': response.data.translated_strings.locale,
}
// Make from JSON object array of objects
for (const [key, value] of Object.entries(response.data.default_strings)) {
this.defaultStrings.push({
'key': key,
'value': value,
})
}
this.filterStrings()
})
.catch(() => Vue.prototype.$isSomethingWrong())
.finally(() => {
this.loadedStrings = true
})
}
},
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
@import '@assets/vue-file-manager/_forms';
.spinner-wrapper {
position: relative;
height: 50%;
.spinner {
top: 60% !important;
}
}
.not-found-wrapper {
display: flex;
margin-top: 20%;
.not-found {
margin: auto;
font-weight: 700;
padding: 10px;
border-radius: 8px;
background: $light_background;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.12);
}
}
.string:last-child {
margin-bottom: 32px !important;
}
.block-form {
padding: 1px;
height: 100%;
}
.disable-switch {
cursor: not-allowed;
/deep/.text-right {
pointer-events: none;
}
}
.language-strings-wrapper {
width: 100%;
height: 100%;
margin: 0 auto;
display: flex;
flex-direction: column;
position: relative;
.block-form{
overflow-y: scroll;
overflow-x: hidden;
}
}
.search-bar-wrapper {
padding: 7px 0px;
}
.search-bar {
position: relative;
width: 100%;
border-radius: 8px;
input {
background: $light-background;
border-radius: 8px;
outline: 0;
padding: 9px 20px 9px 43px;
font-weight: 700;
@include font-size(16);
width: 100%;
height: 50px;
min-width: 175px;
transition: 0.15s all ease;
border: 1px solid transparent;
-webkit-appearance: none;
&::placeholder {
color: $light_text;
@include font-size(14);
font-weight: 700;
}
&:focus {
border: 1px solid $theme;
box-shadow: 0 0 7px rgba($theme, 0.3);
}
&:focus + .icon {
path {
fill: $theme;
}
}
}
.icon {
height: 100%;
position: absolute;
top: 0;
left: 0;
padding: 11px 15px;
display: flex;
align-items: center;
circle,
line {
color: $light_text;
}
.pointer {
cursor: pointer;
}
}
}
// @media only screen and (max-width: 1024px) {
// .search-bar input {
// max-width: 190px;
// padding-right: 0;
// }
// }
@media only screen and (max-width: 690px) {
// .search-bar {
// input {
// min-width: initial;
// width: 100%;
// max-width: initial;
// padding: 9px 20px 9px 30px;
// &:focus {
// box-shadow: none;
// }
// }
// .icon {
// padding: 11px 15px 11px 0;
// }
// }
}
@media (prefers-color-scheme: dark) {
.search-bar {
input {
background: $dark_mode_background ;
&::placeholder {
color: $dark_mode_text_secondary;
}
}
.icon {
circle,
line {
color: $dark_mode_text_secondary !important;
}
}
}
.not-found-wrapper {
.not-found {
background: $dark_mode_foreground !important;
}
}
}
</style>
@@ -20,7 +20,7 @@
<!--Email-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_email') }}</label>
<label>{{ $t('page_registration.label_email') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="email" rules="required" v-slot="{ errors }">
<input v-model="user.email" :placeholder="$t('admin_page_user.create_user.label_email')" type="email" class="focus-border-theme" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
@@ -29,7 +29,7 @@
<!--Name-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_name') }}</label>
<label>{{ $t('page_registration.label_name') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="user name" rules="required" v-slot="{ errors }">
<input v-model="user.name" :placeholder="$t('admin_page_user.create_user.label_name')" type="text" class="focus-border-theme" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
@@ -39,7 +39,7 @@
<!--Password-->
<div class="wrapper-inline">
<div class="block-wrapper">
<label>{{ $t('page_registration.label_pass') }}</label>
<label>{{ $t('page_registration.label_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="password" rules="required" v-slot="{ errors }">
<input v-model="user.password" :placeholder="$t('page_registration.placeholder_pass')" type="password" class="focus-border-theme" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
@@ -47,7 +47,7 @@
</div>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_confirm_pass') }}</label>
<label>{{ $t('page_registration.label_confirm_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="password confirm" rules="required" v-slot="{ errors }">
<input v-model="user.password_confirmation" :placeholder="$t('admin_page_user.create_user.label_conf_pass')" type="password" class="focus-border-theme" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
@@ -34,7 +34,7 @@
<!--Email-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_email') }}</label>
<label>{{ $t('page_registration.label_email') }}:</label>
<div class="input-wrapper">
<input :value="user.data.attributes.email"
:placeholder="$t('page_registration.placeholder_email')"
@@ -46,7 +46,7 @@
<!--Name-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_name') }}</label>
<label>{{ $t('page_registration.label_name') }}:</label>
<div class="input-wrapper">
<input :value="user.data.relationships.settings.data.attributes.name"
:placeholder="$t('page_registration.placeholder_name')"
@@ -7,13 +7,13 @@
<b v-if="! config.app_logo" class="auth-logo-text">{{ config.app_name }}</b>
<h1>{{ $t('page_create_password.title') }}</h1>
<h2>{{ $t('page_create_password.subtitle') }}</h2>
<h2>{{ $t('page_create_password.subtitle') }}:</h2>
<ValidationObserver @submit.prevent="createNewPassword" ref="create_new_password" v-slot="{ invalid }"
tag="form" class="form block-form create-new-password">
<div class="block-wrapper">
<label>{{ $t('page_create_password.label_email') }}</label>
<label>{{ $t('page_create_password.label_email') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="recoverPassword.email" :placeholder="$t('page_login.placeholder_email')" type="email"
@@ -7,7 +7,7 @@
<b v-if="! config.app_logo" class="auth-logo-text">{{ config.app_name }}</b>
<h1>{{ $t('page_forgotten_password.title') }}</h1>
<h2>{{ $t('page_forgotten_password.subtitle') }}</h2>
<h2>{{ $t('page_forgotten_password.subtitle') }}:</h2>
<ValidationObserver @submit.prevent="forgottenPassword" ref="forgotten_password" v-slot="{ invalid }"
tag="form" class="form inline-form">
+2 -2
View File
@@ -7,7 +7,7 @@
<b v-if="! config.app_logo" class="auth-logo-text">{{ config.app_name }}</b>
<h1>{{ $t('page_login.title') }}</h1>
<h2>{{ $t('page_login.subtitle') }}</h2>
<h2>{{ $t('page_login.subtitle') }}:</h2>
<ValidationObserver @submit.prevent="logIn" ref="log_in" v-slot="{ invalid }" tag="form"
class="form inline-form">
@@ -37,7 +37,7 @@
<div class="user" v-if="checkedAccount">
<img class="user-avatar" :src="checkedAccount.avatar" :alt="checkedAccount.name">
<h1>{{ $t('page_sign_in.title', {name: checkedAccount.name}) }}</h1>
<h2>{{ $t('page_sign_in.subtitle') }}</h2>
<h2>{{ $t('page_sign_in.subtitle') }}:</h2>
</div>
<ValidationObserver @submit.prevent="singIn" ref="sign_in" v-slot="{ invalid }" tag="form"
+5 -5
View File
@@ -7,13 +7,13 @@
<b v-if="! config.app_logo" class="auth-logo-text">{{ config.app_name }}</b>
<h1>{{ $t('page_registration.title') }}</h1>
<h2>{{ $t('page_registration.subtitle') }}</h2>
<h2>{{ $t('page_registration.subtitle') }}:</h2>
<ValidationObserver @submit.prevent="signUp" ref="sign_up" v-slot="{ invalid }" tag="form"
class="form block-form">
<div class="block-wrapper">
<label>{{ $t('page_registration.label_email') }}</label>
<label>{{ $t('page_registration.label_email') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="register.email" :placeholder="$t('page_registration.placeholder_email')" type="email"
@@ -24,7 +24,7 @@
</div>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_name') }}</label>
<label>{{ $t('page_registration.label_name') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Full Name" rules="required"
v-slot="{ errors }">
<input v-model="register.name" :placeholder="$t('page_registration.placeholder_name')" type="text"
@@ -35,7 +35,7 @@
</div>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_pass') }}</label>
<label>{{ $t('page_registration.label_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Your New Password"
rules="required" v-slot="{ errors }">
<input v-model="register.password" :placeholder="$t('page_registration.placeholder_pass')" type="password"
@@ -46,7 +46,7 @@
</div>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_confirm_pass') }}</label>
<label>{{ $t('page_registration.label_confirm_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Your Password"
rules="required" v-slot="{ errors }">
<input v-model="register.password_confirmation" :placeholder="$t('page_registration.placeholder_confirm_pass')"
@@ -63,6 +63,13 @@
routeName: 'Pages',
isVisible: true,
},
{
icon: 'language',
title: this.$t('admin_menu.language'),
routeName: 'Language',
isVisible: true,
}
],
SassNavigation: [
{
+2 -2
View File
@@ -4,7 +4,7 @@
<div class="form block-form">
<FormLabel>{{ $t('user_settings.title_account') }}</FormLabel>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_email') }}</label>
<label>{{ $t('page_registration.label_email') }}:</label>
<div class="input-wrapper">
<input :value="userInfo.email"
:placeholder="$t('page_registration.placeholder_email')"
@@ -14,7 +14,7 @@
</div>
</div>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_name') }}</label>
<label>{{ $t('page_registration.label_name') }}:</label>
<div class="input-wrapper">
<input @keyup="changeUserName"
v-model="userInfo.name"