Работа над проектом
This commit is contained in:
@@ -29,7 +29,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DivBtn class="q-mx-md text-white bg-secondary" :size="30" :icon-size="24" :imt="1" icon="la la-cog" round @click="settingsDialogVisible = true" />
|
||||
<DivBtn class="q-mx-md text-white bg-secondary" :size="30" :icon-size="24" :imt="1" icon="la la-cog" round @click="settingsDialogVisible = true">
|
||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%" max-width="400px">
|
||||
Настройки
|
||||
</q-tooltip>
|
||||
</DivBtn>
|
||||
|
||||
<div class="col"></div>
|
||||
<div class="q-px-sm q-py-xs bg-green-12" style="border: 1px solid #aaaaaa; border-radius: 6px">
|
||||
@@ -57,19 +61,33 @@
|
||||
class="bg-white q-mt-xs" input-style="cursor: pointer" style="width: 200px;" label="Жанр" stack-label outlined dense clearable readonly
|
||||
@click="selectGenre"
|
||||
>
|
||||
<q-tooltip v-if="genreNames" :delay="500" anchor="bottom right" content-style="font-size: 80%" max-width="400px">
|
||||
<q-tooltip v-if="genreNames" :delay="500" anchor="bottom middle" content-style="font-size: 80%" max-width="400px">
|
||||
{{ genreNames }}
|
||||
</q-tooltip>
|
||||
</q-tooltip>
|
||||
</q-input>
|
||||
<div class="q-mx-xs" />
|
||||
<q-input
|
||||
v-model="lang" :maxlength="inputMaxLength" :debounce="inputDebounce"
|
||||
class="bg-white q-mt-xs" input-style="cursor: pointer" style="width: 80px;" label="Язык" stack-label outlined dense clearable readonly
|
||||
@click="selectLang"
|
||||
/>
|
||||
<div class="q-mx-xs" />
|
||||
>
|
||||
<q-tooltip v-if="lang" :delay="500" anchor="bottom middle" content-style="font-size: 80%" max-width="400px">
|
||||
{{ lang }}
|
||||
</q-tooltip>
|
||||
</q-input>
|
||||
|
||||
<DivBtn class="text-white bg-grey-13" :size="30" :icon-size="24" icon="la la-question" round @click="showSearchHelp" />
|
||||
<div class="q-mx-xs" />
|
||||
<DivBtn class="text-white bg-grey-13" :size="30" :icon-size="24" icon="la la-broom" round @click="setDefaults">
|
||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%" max-width="400px">
|
||||
Сбросить поиск
|
||||
</q-tooltip>
|
||||
</DivBtn>
|
||||
<div class="q-mx-xs" />
|
||||
<DivBtn class="text-white bg-grey-13" :size="30" :icon-size="24" icon="la la-question" round @click="showSearchHelp">
|
||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%" max-width="400px">
|
||||
Подсказка
|
||||
</q-tooltip>
|
||||
</DivBtn>
|
||||
|
||||
<div class="q-mx-xs" />
|
||||
<div class="row items-center q-mt-xs">
|
||||
@@ -93,7 +111,7 @@
|
||||
<div class="row items-center q-ml-md q-mr-xs no-wrap">
|
||||
<!--div style="min-width: 35px">
|
||||
<DivBtn v-if="tableData.length > 1" :icon-size="24" icon="la la-check-circle" @click="selectAuthor(item.author)">
|
||||
<q-tooltip :delay="1500" anchor="bottom right" content-style="font-size: 80%">
|
||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">
|
||||
Только этот автор
|
||||
</q-tooltip>
|
||||
</DivBtn>
|
||||
@@ -171,6 +189,7 @@
|
||||
</Dialog>
|
||||
|
||||
<SelectGenreDialog v-model="selectGenreDialogVisible" v-model:genre="genre" :genre-tree="genreTree" />
|
||||
<SelectLangDialog v-model="selectLangDialogVisible" v-model:lang="lang" :lang-list="langList" :lang-default="langDefault" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -181,6 +200,8 @@ import { reactive } from 'vue';
|
||||
|
||||
import PageScroller from './PageScroller/PageScroller.vue';
|
||||
import SelectGenreDialog from './SelectGenreDialog/SelectGenreDialog.vue';
|
||||
import SelectLangDialog from './SelectLangDialog/SelectLangDialog.vue';
|
||||
|
||||
import authorBooksStorage from './authorBooksStorage';
|
||||
import DivBtn from '../share/DivBtn.vue';
|
||||
import Dialog from '../share/Dialog.vue';
|
||||
@@ -193,6 +214,7 @@ const componentOptions = {
|
||||
components: {
|
||||
PageScroller,
|
||||
SelectGenreDialog,
|
||||
SelectLangDialog,
|
||||
Dialog,
|
||||
DivBtn
|
||||
},
|
||||
@@ -250,6 +272,7 @@ class Search {
|
||||
loadingMessage2 = '';
|
||||
settingsDialogVisible = false;
|
||||
selectGenreDialogVisible = false;
|
||||
selectLangDialogVisible = false;
|
||||
|
||||
page = 1;
|
||||
pageCount = 1;
|
||||
@@ -271,6 +294,7 @@ class Search {
|
||||
showCounts = true;
|
||||
showDeleted = false;
|
||||
abCacheEnabled = true;
|
||||
langDefault = '';
|
||||
|
||||
//stuff
|
||||
queryFound = -1;
|
||||
@@ -278,6 +302,7 @@ class Search {
|
||||
bookRowsOnPage = 100;
|
||||
inpxHash = '';
|
||||
genreTree = [];
|
||||
langList = [];
|
||||
genreTreeInpxHash = '';
|
||||
|
||||
limitOptions = [
|
||||
@@ -308,6 +333,10 @@ class Search {
|
||||
if (!this.$root.isMobileDevice)
|
||||
this.$refs.authorInput.focus();
|
||||
|
||||
this.setDefaults();
|
||||
|
||||
//query from url parse
|
||||
|
||||
this.ready = true;
|
||||
this.refresh();//no await
|
||||
})();
|
||||
@@ -321,6 +350,7 @@ class Search {
|
||||
this.showCounts = settings.showCounts;
|
||||
this.showDeleted = settings.showDeleted;
|
||||
this.abCacheEnabled = settings.abCacheEnabled;
|
||||
this.langDefault = settings.langDefault;
|
||||
}
|
||||
|
||||
get config() {
|
||||
@@ -373,7 +403,7 @@ class Search {
|
||||
}
|
||||
|
||||
selectLang() {
|
||||
this.$root.stdDialog.alert('Выбор языка');
|
||||
this.selectLangDialogVisible = true;
|
||||
}
|
||||
|
||||
onScroll() {
|
||||
@@ -434,9 +464,7 @@ class Search {
|
||||
}
|
||||
|
||||
setSetting(name, newValue) {
|
||||
const newSettings = _.cloneDeep(this.settings);
|
||||
newSettings[name] = _.cloneDeep(newValue);
|
||||
this.commit('setSettings', newSettings);
|
||||
this.commit('setSettings', {[name]: _.cloneDeep(newValue)});
|
||||
}
|
||||
|
||||
expandAuthor(item) {
|
||||
@@ -566,6 +594,7 @@ class Search {
|
||||
}
|
||||
|
||||
this.genreTree = result.genreTree;
|
||||
this.langList = result.langList;
|
||||
this.genreTreeInpxHash = result.inpxHash;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -606,6 +635,14 @@ class Search {
|
||||
this.tableData = result;
|
||||
}
|
||||
|
||||
setDefaults() {
|
||||
this.author = '';
|
||||
this.series = '';
|
||||
this.title = '';
|
||||
this.genre = '';
|
||||
this.lang = this.langDefault;
|
||||
}
|
||||
|
||||
async refresh() {
|
||||
if (!this.ready)
|
||||
return;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div ref="box" class="column q-mt-xs overflow-auto no-wrap" style="width: 350px; padding: 0px 10px 10px 10px;">
|
||||
<div ref="box" class="column q-mt-xs overflow-auto no-wrap" style="width: 370px; padding: 0px 10px 10px 10px;">
|
||||
<div class="row items-center top-panel bg-grey-3">
|
||||
<q-input ref="search" v-model="search" class="col" outlined dense bg-color="white" placeholder="Найти" clearable />
|
||||
</div>
|
||||
|
||||
190
client/components/Search/SelectLangDialog/SelectLangDialog.vue
Normal file
190
client/components/Search/SelectLangDialog/SelectLangDialog.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<Dialog ref="dialog" v-model="dialogVisible">
|
||||
<template #header>
|
||||
<div class="row items-center">
|
||||
<div style="font-size: 130%">
|
||||
Выбрать язык
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div ref="box" class="column q-mt-xs overflow-auto no-wrap" style="width: 370px; padding: 0px 10px 10px 10px;">
|
||||
<div v-show="langList.length" class="checkbox-tick-all">
|
||||
<div class="row items-center">
|
||||
<q-option-group
|
||||
v-model="ticked"
|
||||
:options="optionsPre"
|
||||
type="checkbox"
|
||||
inline
|
||||
/>
|
||||
|
||||
<div class="col" />
|
||||
<div v-show="lang != langDefault" class="clickable" @click="setAsDefaults">
|
||||
Установить по умолчанию
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<q-checkbox v-model="tickAll" label="Выбрать/снять все" toggle-order="ft" @update:model-value="makeTickAll" />
|
||||
</div>
|
||||
|
||||
<q-option-group
|
||||
v-model="ticked"
|
||||
:options="options"
|
||||
type="checkbox"
|
||||
inline
|
||||
>
|
||||
<template #label="opt">
|
||||
<div class="row items-center" style="width: 35px">
|
||||
<span>{{ opt.label }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</q-option-group>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">
|
||||
OK
|
||||
</q-btn>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//-----------------------------------------------------------------------------
|
||||
import vueComponent from '../../vueComponent.js';
|
||||
|
||||
import Dialog from '../../share/Dialog.vue';
|
||||
|
||||
const componentOptions = {
|
||||
components: {
|
||||
Dialog
|
||||
},
|
||||
watch: {
|
||||
modelValue(newValue) {
|
||||
this.dialogVisible = newValue;
|
||||
if (newValue)
|
||||
this.init();//no await
|
||||
},
|
||||
dialogVisible(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
},
|
||||
lang() {
|
||||
this.updateTicked();
|
||||
},
|
||||
ticked() {
|
||||
this.checkAllTicked();
|
||||
this.updateLang();
|
||||
},
|
||||
}
|
||||
};
|
||||
class SelectLangDialog {
|
||||
_options = componentOptions;
|
||||
_props = {
|
||||
modelValue: Boolean,
|
||||
lang: {type: String, value: ''},
|
||||
langDefault: {type: String, value: ''},
|
||||
langList: Array,
|
||||
};
|
||||
|
||||
dialogVisible = false;
|
||||
|
||||
ticked = [];
|
||||
tickAll = false;
|
||||
|
||||
created() {
|
||||
this.commit = this.$store.commit;
|
||||
}
|
||||
|
||||
mounted() {
|
||||
}
|
||||
|
||||
async init() {
|
||||
//await this.$refs.dialog.waitShown();
|
||||
}
|
||||
|
||||
get options() {
|
||||
const result = [];
|
||||
|
||||
for (const lang of this.langList) {
|
||||
result.push({label: lang, value: lang});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
get optionsPre() {
|
||||
const result = [];
|
||||
|
||||
for (const lang of this.langList) {
|
||||
if (['ru', 'en'].includes(lang)) {
|
||||
result.push({label: lang, value: lang});
|
||||
}
|
||||
}
|
||||
|
||||
return result.reverse();
|
||||
}
|
||||
|
||||
makeTickAll() {
|
||||
if (this.tickAll) {
|
||||
const newTicked = [];
|
||||
for (const lang of this.langList) {
|
||||
newTicked.push(lang);
|
||||
}
|
||||
this.ticked = newTicked;
|
||||
} else {
|
||||
this.ticked = [];
|
||||
this.tickAll = false;
|
||||
}
|
||||
}
|
||||
|
||||
checkAllTicked() {
|
||||
const ticked = new Set(this.ticked);
|
||||
|
||||
let newTickAll = !!(this.langList.length);
|
||||
for (const lang of this.langList) {
|
||||
if (!ticked.has(lang)) {
|
||||
newTickAll = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.ticked.length && !newTickAll) {
|
||||
this.tickAll = undefined;
|
||||
} else {
|
||||
this.tickAll = newTickAll;
|
||||
}
|
||||
}
|
||||
|
||||
updateTicked() {
|
||||
this.ticked = this.lang.split(',').filter(s => s);
|
||||
}
|
||||
|
||||
updateLang() {
|
||||
this.$emit('update:lang', this.ticked.join(','));
|
||||
}
|
||||
|
||||
setAsDefaults() {
|
||||
this.commit('setSettings', {langDefault: this.lang});
|
||||
}
|
||||
|
||||
okClick() {
|
||||
this.dialogVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
export default vueComponent(SelectLangDialog);
|
||||
//-----------------------------------------------------------------------------
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.checkbox-tick-all {
|
||||
border-bottom: 1px solid #bbbbbb;
|
||||
margin-bottom: 7px;
|
||||
padding: 5px 5px 2px 0px;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
color: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@@ -33,8 +33,9 @@ import {QDialog} from 'quasar/src/components/dialog';
|
||||
//import {QChip} from 'quasar/src/components/chip';
|
||||
import {QTree} from 'quasar/src/components/tree';
|
||||
//import {QVirtualScroll} from 'quasar/src/components/virtual-scroll';
|
||||
|
||||
//import {QExpansionItem} from 'quasar/src/components/expansion-item';
|
||||
import {QOptionGroup} from 'quasar/src/components/option-group';
|
||||
|
||||
|
||||
const components = {
|
||||
//QLayout,
|
||||
@@ -66,6 +67,7 @@ const components = {
|
||||
QTree,
|
||||
//QExpansionItem,
|
||||
//QVirtualScroll,
|
||||
QOptionGroup,
|
||||
};
|
||||
|
||||
//directives
|
||||
|
||||
@@ -7,6 +7,7 @@ const state = {
|
||||
showCounts: true,
|
||||
showDeleted: false,
|
||||
abCacheEnabled: true,
|
||||
langDefault: '',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -22,7 +23,7 @@ const mutations = {
|
||||
state.config = value;
|
||||
},
|
||||
setSettings(state, value) {
|
||||
state.settings = value;
|
||||
state.settings = Object.assign({}, state.settings, value);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ class WebWorker {
|
||||
|
||||
//добавим к жанрам те, что нашлись при парсинге
|
||||
const genreParsed = new Set();
|
||||
const rows = await db.select({table: 'genre', map: `(r) => ({value: r.value})`});
|
||||
let rows = await db.select({table: 'genre', map: `(r) => ({value: r.value})`});
|
||||
for (const row of rows) {
|
||||
genreParsed.add(row.value);
|
||||
|
||||
@@ -245,8 +245,13 @@ class WebWorker {
|
||||
genres.splice(j--, 1);
|
||||
}
|
||||
|
||||
// langs
|
||||
rows = await db.select({table: 'lang', map: `(r) => ({value: r.value})`});
|
||||
const langs = rows.map(r => r.value);
|
||||
|
||||
result = {
|
||||
genreTree: genres,
|
||||
langList: langs,
|
||||
inpxHash: (config.inpxHash ? config.inpxHash : ''),
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user