Language editor refactoring part 4 (backend + frontend)

This commit is contained in:
Peter Papp
2021-04-01 10:40:48 +02:00
parent 5130082111
commit 7772ef6b40
32 changed files with 288 additions and 161 deletions
@@ -32,7 +32,7 @@
<ul v-if="config.isAuthenticated" class="navigation-links">
<li v-if="config.userRegistration">
<router-link class="cta-button text-theme bg-theme-100" :to="{name: 'Files'}">
Go to Files <!--todo: preklad-->
{{ $t('go_to_files') }}
</router-link>
</li>
</ul>
@@ -11,7 +11,7 @@
<!--More Actions-->
<div @click="showMobileNavigation" class="mobile-menu">
<menu-icon size="17" class="icon"></menu-icon>
<menu-icon size="17" class="icon" />
</div>
</header>
</template>
@@ -2,8 +2,7 @@
<PopupWrapper name="create-language">
<!--Title-->
<!--TODO: jazyk-->
<PopupHeader title="Create Language" icon="edit" />
<PopupHeader :title="$t('create_language')" icon="edit" />
<!--Content-->
<PopupContent>
@@ -12,14 +11,14 @@
<ValidationObserver @submit.prevent="createLanguage" ref="createForm" v-slot="{ invalid }" tag="form" class="form-wrapper">
<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="form.locale" :options="locals" placeholder="Select Language Locale" :isError="errors[0]" />
<label class="input-label">{{ $t('select_locale') }}:</label>
<SelectInput v-model="form.locale" :options="locales" :placeholder="$t('select_language_locale')" :isError="errors[0]" />
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<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="form.name" :class="{'is-error': errors[0]}" type="text" ref="input" class="focus-border-theme" placeholder="Type Language Name">
<label class="input-label">{{ $t('locale_name') }}:</label>
<input v-model="form.name" :class="{'is-error': errors[0]}" type="text" ref="input" class="focus-border-theme" :placeholder="$t('type_language_name')">
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</ValidationObserver>
@@ -32,7 +31,7 @@
@click.native="$closePopup()"
button-style="secondary"
>
Cancel
{{ $t('global.cancel') }}
</ButtonBase>
<ButtonBase
class="popup-button"
@@ -41,7 +40,7 @@
:loading="isLoading"
:disabled="isLoading"
>
Create Language
{{ $t('create_language') }}
</ButtonBase>
</PopupActions>
</PopupWrapper>
@@ -79,7 +78,7 @@ export default {
locale: undefined,
},
isLoading: false,
locals: [
locales: [
{
value: "ab",
label: "Abkhaz"
@@ -851,10 +850,6 @@ export default {
})
}
},
},
mounted() {
this.name = undefined,
this.locale = undefined
}
}
</script>
@@ -9,10 +9,10 @@
<input
v-model="query"
@input="$emit('input', query)"
class="query"
class="query focus-border-theme"
type="text"
name="searchInput"
placeholder="Search Language Strings..."
:placeholder="$t('search_translations')"
/>
</div>
</template>
@@ -34,7 +34,6 @@ export default {
methods: {
clearInput() {
this.query = undefined
this.$emit('reset-query')
},
},
@@ -74,13 +73,13 @@ export default {
}
&:focus {
border: 1px solid $theme;
box-shadow: 0 0 7px rgba($theme, 0.3);
border-width: 1px;
border-style: solid;
}
&:focus + .icon {
path {
fill: $theme;
color: inherit;
}
}
}
@@ -105,4 +104,12 @@ export default {
}
}
@media (prefers-color-scheme: dark) {
.search-bar {
input {
background: $dark_mode_foreground;
}
}
}
</style>
+2 -2
View File
@@ -33,7 +33,7 @@
<!--Permision Select-->
<ValidationProvider v-if="isFolder" tag="div" mode="passive" class="input-wrapper" name="Permission" rules="required" v-slot="{ errors }">
<label class="input-label">{{ $t('shared_form.label_permission') }}:</label>
<SelectInput v-model="shareOptions.permission" :options="permissionOptions" :default="shareOptions.permission" :placeholder="$t('shared_form.placeholder_permission')" :isError="errors[0]"/>
<SelectInput v-model="shareOptions.permission" :options="$translateSelectOptions(permissionOptions)" :default="shareOptions.permission" :placeholder="$t('shared_form.placeholder_permission')" :isError="errors[0]"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -60,7 +60,7 @@
<!--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"/>
<SelectBoxInput v-model="shareOptions.expiration" :data="$translateSelectOptions(expirationList)" :value="shareOptions.expiration" class="box"/>
</div>
</div>
-1
View File
@@ -292,7 +292,6 @@ const routesAdmin = [
import(/* webpackChunkName: "chunks/app-language" */ './views/Admin/Languages/Language'),
meta: {
requiresAuth: true,
title: 'routes_title.language'
},
}
]
+5
View File
@@ -1,6 +1,9 @@
<template>
<section id="viewport">
<!--Mobile Navigation-->
<MobileNavigation />
<!--Confirm Popup-->
<Confirm />
@@ -87,6 +90,7 @@
<script>
import { UsersIcon, SettingsIcon, FileTextIcon, CreditCardIcon, DatabaseIcon, BoxIcon, MonitorIcon, GlobeIcon } from 'vue-feather-icons'
import MobileNavigation from '@/components/Others/MobileNavigation'
import ContentSidebar from '@/components/Sidebar/ContentSidebar'
import CreateLanguage from '@/components/Others/CreateLanguage'
import ContentGroup from '@/components/Sidebar/ContentGroup'
@@ -100,6 +104,7 @@
...mapGetters(['config']),
},
components: {
MobileNavigation,
CreateLanguage,
ContentSidebar,
CreditCardIcon,
@@ -26,13 +26,12 @@
<FormLabel class="mt-70">{{ $t('admin_settings.appearance.section_appearance') }}</FormLabel>
<!--TODO: add language-->
<div class="block-wrapper">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Title" rules="required" v-slot="{ errors }">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">Color Theme:</label>
<small class="input-help">Your color change will be visible after app refresh.</small>
<label class="input-label">{{ $t('color_theme') }}:</label>
<small class="input-help">{{ $t('color_theme_description') }}</small>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</div>
<input @input="$updateText('/admin/settings', 'app_color', app.color)" v-model="app.color" :placeholder="$t('admin_settings.appearance.title_plac')" type="color"
@@ -63,21 +62,19 @@
</ValidationProvider>
</div>
<!--TODO: add language-->
<div class="block-wrapper">
<label>OG Image:</label>
<label>{{ $t('og_image') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Favicon" v-slot="{ errors }">
<ImageInput @input="$updateImage('/admin/settings', 'app_og_image', app.og_image)" :image="$getImage(app.og_image)" v-model="app.og_image" :error="errors[0]"/>
<small class="input-help">Image that appear when someone shares the content to Facebook or any other social medium. Preferred size is 1200x627</small>
<small class="input-help">{{ $t('og_image_description') }}</small>
</ValidationProvider>
</div>
<!--TODO: add language-->
<div class="block-wrapper">
<label>App Touch Icon:</label>
<label>{{ $t('app_touch_icon') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Favicon" v-slot="{ errors }">
<ImageInput @input="$updateImage('/admin/settings', 'app_touch_icon', app.touch_icon)" :image="$getImage(app.touch_icon)" v-model="app.touch_icon" :error="errors[0]"/>
<small class="input-help">If user store bookmark on his phone screen, this icon appear in app thumbnail. Preferred size is 156x156</small>
<small class="input-help">{{ $t('app_touch_icon_description') }}</small>
</ValidationProvider>
</div>
</div>
+1 -1
View File
@@ -10,7 +10,7 @@
</a>
</div>
<div class="metadata">
<a href="https://vuefilemanager.com/changelog" target="_blank" class="meta">
<a href="https://gist.github.com/MakingCG/9c07f8af392081ae5d5290d920a79b5d" target="_blank" class="meta">
<span class="meta-title">{{ $t('admin_page_dashboard.version') }}:</span>
<ColorLabel color="purple">
{{ data.app_version }}
+69 -45
View File
@@ -1,8 +1,8 @@
<template>
<div id="single-page">
<div id="page-content">
<MobileHeader title="Languages" />
<PageHeader title="Languages" />
<MobileHeader :title="$t('routes_title.language')" />
<PageHeader :title="$t('routes_title.language')" />
<div v-if="languages" class="content-page">
@@ -12,14 +12,14 @@
<div class="sticky top-65">
<div class="languages-wrapper page-tab from-fixed-width">
<div class="language-label-wrapper">
<label class="language-label">Languages</label>
<label class="language-label">{{ $t('languages') }}</label>
</div>
<!-- Languages -->
<div class="all-language-wrapper">
<div @click="getLanguage(language)" v-for="language in languages" :key="language.data.id" class="language">
<div @click="getLanguage(language)" v-for="language in languages" :key="language.data.id" class="language group">
<label class="name" :class="{'active': selectedLanguage && selectedLanguage.data.attributes.locale === language.data.attributes.locale}">
{{ language.data.attributes.name }}
<span class="active-text-theme group-hover-text-theme">{{ language.data.attributes.name }}</span>
</label>
<x-icon
v-if="language.data.attributes.locale !== 'en'"
@@ -32,7 +32,7 @@
</div>
<MobileActionButton @click.native="createLanguage" icon="plus" class="button-add-language">
Add Language
{{ $t('add_language') }}
</MobileActionButton>
</div>
</div>
@@ -40,36 +40,16 @@
<!--Content-->
<div class="form block-form content">
<div v-if="! selectedLanguage">
<Spinner />
</div>
<Spinner v-if="! selectedLanguage" />
<div v-if="selectedLanguage">
<FormLabel icon="settings">
Language Settings
{{ $t('language_settings') }}
</FormLabel>
<!--Set default language-->
<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="$updateText(`/admin/languages/${selectedLanguage.data.id}`, 'language', selectedLanguage.data.attributes.locale)"
class="switch"
:class="{'disable-switch': selectedLanguage.data.attributes.locale !== }"
/>
</div>
</div>
</div>
<!--Language name-->
<div class="block-wrapper">
<label>Language Name:</label>
<label>{{ $t('language_name') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Description" rules="required" v-slot="{ errors }">
<input @input="$updateText(`/admin/languages/${selectedLanguage.data.id}`, 'name', selectedLanguage.data.attributes.name)" v-model="selectedLanguage.data.attributes.name"
:placeholder="$t('admin_settings.appearance.description_plac')" type="text" :class="{'is-error': errors[0]}" class="focus-border-theme" />
@@ -77,18 +57,45 @@
</ValidationProvider>
</div>
<!--Set default language-->
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">
{{ $t('set_as_default_language') }}:
</label>
<small class="input-help">
If this language is set as default, app will appear in this language for all users.
</small>
</div>
<SwitchInput
@input="setDefaultLanguage"
class="switch"
:class="{'disable-switch': selectedLanguage.data.attributes.locale === this.defaultLanguageLocale }"
:state="selectedLanguage.data.attributes.locale === this.defaultLanguageLocale"
/>
</div>
</div>
</div>
<!--Translations-->
<FormLabel class="mt-70">
Edit Translations
{{ $t('edit_translations') }}
</FormLabel>
<InfoBox class="info-box">
<p>Please preserve in your translations special string variables defined in format as <b class="text-theme">:variable</b> or <b class="text-theme">{variable}</b>.</p>
</InfoBox>
<!--Inline Search-->
<div class="block-wrapper sticky top-50 search-bar-wrapper">
<SearchInput v-model="query" @reset-query="query = ''" />
</div>
<!--Translation-->
<div class="block-wrapper" v-for="(translation, key) in translationList" :key="key">
<label> {{ defaultTranslations[key] }}:</label>
<label> {{ referenceTranslations[key] }}:</label>
<ValidationProvider tag="div" class="input-wrapper" name="Language string" rules="required" v-slot="{ errors }">
<input type="text"
:class="{'is-error': errors[0]}"
@@ -116,6 +123,7 @@
import FormLabel from '@/components/Others/Forms/FormLabel'
import MobileHeader from '@/components/Mobile/MobileHeader'
import ButtonBase from '@/components/FilesView/ButtonBase'
import InfoBox from '@/components/Others/Forms/InfoBox'
import PageHeader from '@/components/Others/PageHeader'
import Spinner from '@/components/FilesView/Spinner'
import {PlusIcon, XIcon} from 'vue-feather-icons'
@@ -135,40 +143,48 @@
PageHeader,
FormLabel,
PlusIcon,
InfoBox,
Spinner,
XIcon
},
data() {
return {
defaultTranslations: undefined,
searchedTranslationResults: undefined,
referenceTranslations: undefined,
defaultLanguageLocale: undefined,
selectedLanguage: undefined,
occurrences: undefined,
languages: undefined,
query: '',
}
},
watch: {
query: debounce(function (val) {
this.occurrences = omitBy(this.selectedLanguage.data.attributes.translations, (string, key) => {
this.searchedTranslationResults = omitBy(this.selectedLanguage.data.attributes.translations, string => {
return !string.toLowerCase().includes(val.toLowerCase())
})
}, 300),
},
computed: {
translationList() {
return this.occurrences && this.query !== ''
? this.occurrences
return this.searchedTranslationResults && this.query !== ''
? this.searchedTranslationResults
: this.selectedLanguage.data.attributes.translations
}
},
methods: {
setDefaultLanguage() {
this.$updateText('/admin/settings', 'language', this.selectedLanguage.data.attributes.locale)
this.defaultLanguageLocale = this.selectedLanguage.data.attributes.locale
},
getLanguages() {
axios
.get('/api/admin/languages')
.then(response => {
this.languages = response.data.data
this.defaultTranslations = response.data.meta.default_translations
this.referenceTranslations = response.data.meta.reference_translations
this.selectedLanguage = response.data.meta.current_language
this.defaultLanguageLocale = response.data.meta.current_language.data.attributes.locale
})
.catch(() => {
this.$isSomethingWrong()
@@ -243,6 +259,18 @@
}
}
.disable-switch {
cursor: not-allowed;
/deep/ .text-right {
pointer-events: none;
}
}
.info-box {
margin-bottom: 12px;
}
.side-content {
flex: 0 0 225px;
@@ -275,10 +303,6 @@
.icon {
display: block;
}
.name {
color: $theme !important;
}
}
.name {
@@ -294,10 +318,6 @@
cursor: pointer;
}
.active {
color: $theme !important;
}
}
}
@@ -327,6 +347,10 @@
@media (prefers-color-scheme: dark) {
.search-bar-wrapper {
background: $dark_mode_background;
}
.language {
.name {
@@ -65,7 +65,7 @@
},
{
icon: 'language',
title: this.$t('admin_menu.language'),
title: this.$t('languages'),
routeName: 'Language',
isVisible: true,