mirror of
https://github.com/simon987/sist2.git
synced 2025-12-19 18:24:54 +00:00
web UI rewrite, switch to ndjson.zst index format
This commit is contained in:
265
sist2-vue/src/views/Configuration.vue
Normal file
265
sist2-vue/src/views/Configuration.vue
Normal file
@@ -0,0 +1,265 @@
|
||||
<template>
|
||||
<!-- <div :style="{width: `${$store.getters.optContainerWidth}px`}"-->
|
||||
<div
|
||||
v-if="!configLoading"
|
||||
style="margin-left: auto; margin-right: auto;" class="container">
|
||||
|
||||
<b-card>
|
||||
<b-card-title>
|
||||
<GearIcon></GearIcon>
|
||||
{{ $t("config") }}
|
||||
</b-card-title>
|
||||
<p>{{ $t("configDescription") }}</p>
|
||||
|
||||
<b-card-body>
|
||||
<h4>{{ $t("displayOptions") }}</h4>
|
||||
|
||||
<b-card>
|
||||
<b-form-checkbox :checked="optLightboxLoadOnlyCurrent" @input="setOptLightboxLoadOnlyCurrent">
|
||||
{{ $t("opt.lightboxLoadOnlyCurrent") }}
|
||||
</b-form-checkbox>
|
||||
|
||||
<label>{{ $t("opt.lang") }}</label>
|
||||
<b-form-select :options="langOptions" :value="optLang" @input="setOptLang"></b-form-select>
|
||||
|
||||
<label>{{ $t("opt.theme") }}</label>
|
||||
<b-form-select :options="themeOptions" :value="optTheme" @input="setOptTheme"></b-form-select>
|
||||
|
||||
<label>{{ $t("opt.displayMode") }}</label>
|
||||
<b-form-select :options="displayModeOptions" :value="optDisplay" @input="setOptDisplay"></b-form-select>
|
||||
|
||||
<label>{{ $t("opt.columns") }}</label>
|
||||
<b-form-select :options="columnsOptions" :value="optColumns" @input="setOptColumns"></b-form-select>
|
||||
</b-card>
|
||||
|
||||
<br/>
|
||||
<h4>{{ $t("searchOptions") }}</h4>
|
||||
<b-card>
|
||||
<b-form-checkbox :checked="optHighlight" @input="setOptHighlight">{{ $t("opt.highlight") }}</b-form-checkbox>
|
||||
<b-form-checkbox :checked="optTagOrOperator" @input="setOptTagOrOperator">{{
|
||||
$t("opt.tagOrOperator")
|
||||
}}
|
||||
</b-form-checkbox>
|
||||
<b-form-checkbox :checked="optFuzzy" @input="setOptFuzzy">{{ $t("opt.fuzzy") }}</b-form-checkbox>
|
||||
<b-form-checkbox :checked="optSearchInPath" @input="setOptSearchInPath">{{
|
||||
$t("opt.searchInPath")
|
||||
}}
|
||||
</b-form-checkbox>
|
||||
<b-form-checkbox :checked="optSuggestPath" @input="setOptSuggestPath">{{
|
||||
$t("opt.suggestPath")
|
||||
}}
|
||||
</b-form-checkbox>
|
||||
|
||||
<br/>
|
||||
<label>{{ $t("opt.fragmentSize") }}</label>
|
||||
<b-form-input :value="optFragmentSize" step="10" type="number" min="0"
|
||||
@input="setOptFragmentSize"></b-form-input>
|
||||
|
||||
<label>{{ $t("opt.resultSize") }}</label>
|
||||
<b-form-input :value="optResultSize" type="number" min="10"
|
||||
@input="setOptResultSize"></b-form-input>
|
||||
|
||||
<label>{{ $t("opt.queryMode") }}</label>
|
||||
<b-form-select :options="queryModeOptions" :value="optQueryMode" @input="setOptQueryMode"></b-form-select>
|
||||
|
||||
<label>{{ $t("opt.slideDuration") }}</label>
|
||||
<b-form-input :value="optLightboxSlideDuration" type="number" min="1"
|
||||
@input="setOptLightboxSlideDuration"></b-form-input>
|
||||
</b-card>
|
||||
|
||||
<h4 class="mt-3">{{ $t("treemapOptions") }}</h4>
|
||||
<b-card>
|
||||
<label>{{ $t("opt.treemapType") }}</label>
|
||||
<b-form-select :value="optTreemapType" :options="treemapTypeOptions"
|
||||
@input="setOptTreemapType"></b-form-select>
|
||||
|
||||
<label>{{ $t("opt.treemapTiling") }}</label>
|
||||
<b-form-select :value="optTreemapTiling" :options="treemapTilingOptions"
|
||||
@input="setOptTreemapTiling"></b-form-select>
|
||||
|
||||
<label>{{ $t("opt.treemapColorGroupingDepth") }}</label>
|
||||
<b-form-input :value="optTreemapColorGroupingDepth" type="number" min="1"
|
||||
@input="setOptTreemapColorGroupingDepth"></b-form-input>
|
||||
|
||||
<label>{{ $t("opt.treemapSize") }}</label>
|
||||
<b-form-select :value="optTreemapSize" :options="treemapSizeOptions"
|
||||
@input="setOptTreemapSize"></b-form-select>
|
||||
|
||||
<template v-if="$store.getters.optTreemapSize === 'custom'">
|
||||
<!-- TODO Width/Height input -->
|
||||
<b-form-input type="number" min="0" step="10"></b-form-input>
|
||||
<b-form-input type="number" min="0" step="10"></b-form-input>
|
||||
</template>
|
||||
|
||||
<label>{{ $t("opt.treemapColor") }}</label>
|
||||
<b-form-select :value="optTreemapColor" :options="treemapColorOptions"
|
||||
@input="setOptTreemapColor"></b-form-select>
|
||||
</b-card>
|
||||
|
||||
<b-button variant="danger" class="mt-4" @click="onResetClick()">{{ $t("configReset") }}</b-button>
|
||||
</b-card-body>
|
||||
</b-card>
|
||||
|
||||
<b-card v-if="loading" class="mt-4">
|
||||
<Preloader></Preloader>
|
||||
</b-card>
|
||||
<DebugInfo v-else></DebugInfo>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import {mapGetters, mapMutations} from "vuex";
|
||||
import DebugInfo from "@/components/DebugInfo.vue";
|
||||
import Preloader from "@/components/Preloader.vue";
|
||||
import sist2 from "@/Sist2Api";
|
||||
import GearIcon from "@/components/GearIcon.vue";
|
||||
|
||||
export default {
|
||||
components: {GearIcon, DebugInfo, Preloader},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
configLoading: false,
|
||||
langOptions: [
|
||||
{value: "en", text: this.$t("lang.en")},
|
||||
{value: "fr", text: this.$t("lang.fr")},
|
||||
],
|
||||
queryModeOptions: [
|
||||
{value: "simple", text: this.$t("queryMode.simple")},
|
||||
{value: "advanced", text: this.$t("queryMode.advanced")}
|
||||
],
|
||||
displayModeOptions: [
|
||||
{value: "grid", text: this.$t("displayMode.grid")},
|
||||
{value: "list", text: this.$t("displayMode.list")}
|
||||
],
|
||||
columnsOptions: [
|
||||
{value: "auto", text: this.$t("columns.auto")},
|
||||
{value: 1, text: "1"},
|
||||
{value: 2, text: "2"},
|
||||
{value: 3, text: "3"},
|
||||
{value: 4, text: "4"},
|
||||
{value: 5, text: "5"},
|
||||
{value: 6, text: "6"},
|
||||
{value: 7, text: "7"},
|
||||
{value: 8, text: "8"},
|
||||
{value: 9, text: "9"},
|
||||
{value: 10, text: "10"},
|
||||
{value: 11, text: "11"},
|
||||
{value: 12, text: "12"},
|
||||
],
|
||||
treemapTypeOptions: [
|
||||
{value: "cascaded", text: this.$t("treemapType.cascaded")},
|
||||
{value: "flat", text: this.$t("treemapType.flat")}
|
||||
],
|
||||
treemapTilingOptions: [
|
||||
{value: "binary", text: this.$t("treemapTiling.binary")},
|
||||
{value: "squarify", text: this.$t("treemapTiling.squarify")},
|
||||
{value: "slice", text: this.$t("treemapTiling.slice")},
|
||||
{value: "dice", text: this.$t("treemapTiling.dice")},
|
||||
{value: "sliceDice", text: this.$t("treemapTiling.sliceDice")},
|
||||
],
|
||||
treemapSizeOptions: [
|
||||
{value: "small", text: this.$t("treemapSize.small")},
|
||||
{value: "medium", text: this.$t("treemapSize.medium")},
|
||||
{value: "large", text: this.$t("treemapSize.large")},
|
||||
{value: "x-large", text: this.$t("treemapSize.xLarge")},
|
||||
{value: "xx-large", text: this.$t("treemapSize.xxLarge")},
|
||||
// {value: "custom", text: this.$t("treemapSize.custom")},
|
||||
],
|
||||
treemapColorOptions: [
|
||||
{value: "PuBuGn", text: "Purple-Blue-Green"},
|
||||
{value: "PuRd", text: "Purple-Red"},
|
||||
{value: "PuBu", text: "Purple-Blue"},
|
||||
{value: "YlOrBr", text: "Yellow-Orange-Brown"},
|
||||
{value: "YlOrRd", text: "Yellow-Orange-Red"},
|
||||
{value: "YlGn", text: "Yellow-Green"},
|
||||
{value: "YlGnBu", text: "Yellow-Green-Blue"},
|
||||
{value: "Plasma", text: "Plasma"},
|
||||
{value: "Magma", text: "Magma"},
|
||||
{value: "Inferno", text: "Inferno"},
|
||||
{value: "Viridis", text: "Viridis"},
|
||||
{value: "Turbo", text: "Turbo"},
|
||||
],
|
||||
themeOptions: [
|
||||
{value: "light", text: this.$t("theme.light")},
|
||||
{value: "black", text: this.$t("theme.black")}
|
||||
]
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
"optTheme",
|
||||
"optDisplay",
|
||||
"optColumns",
|
||||
"optHighlight",
|
||||
"optFuzzy",
|
||||
"optSearchInPath",
|
||||
"optSuggestPath",
|
||||
"optFragmentSize",
|
||||
"optQueryMode",
|
||||
"optTreemapType",
|
||||
"optTreemapTiling",
|
||||
"optTreemapColorGroupingDepth",
|
||||
"optTreemapColor",
|
||||
"optTreemapSize",
|
||||
"optLightboxLoadOnlyCurrent",
|
||||
"optLightboxSlideDuration",
|
||||
"optContainerWidth",
|
||||
"optResultSize",
|
||||
"optTagOrOperator",
|
||||
"optLang"
|
||||
]),
|
||||
clientWidth() {
|
||||
return window.innerWidth;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
sist2.getSist2Info().then(data => {
|
||||
this.$store.commit("setSist2Info", data)
|
||||
this.loading = false;
|
||||
});
|
||||
|
||||
this.$store.subscribe((mutation) => {
|
||||
if (mutation.type.startsWith("setOpt")) {
|
||||
this.$store.dispatch("updateConfiguration");
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
"setOptTheme",
|
||||
"setOptDisplay",
|
||||
"setOptColumns",
|
||||
"setOptHighlight",
|
||||
"setOptFuzzy",
|
||||
"setOptSearchInPath",
|
||||
"setOptSuggestPath",
|
||||
"setOptFragmentSize",
|
||||
"setOptQueryMode",
|
||||
"setOptTreemapType",
|
||||
"setOptTreemapTiling",
|
||||
"setOptTreemapColorGroupingDepth",
|
||||
"setOptTreemapColor",
|
||||
"setOptTreemapSize",
|
||||
"setOptLightboxLoadOnlyCurrent",
|
||||
"setOptLightboxSlideDuration",
|
||||
"setOptContainerWidth",
|
||||
"setOptResultSize",
|
||||
"setOptTagOrOperator",
|
||||
"setOptLang"
|
||||
]),
|
||||
onResetClick() {
|
||||
localStorage.removeItem("sist2_configuration");
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.shrink {
|
||||
flex-grow: inherit;
|
||||
}
|
||||
</style>
|
||||
288
sist2-vue/src/views/SearchPage.vue
Normal file
288
sist2-vue/src/views/SearchPage.vue
Normal file
@@ -0,0 +1,288 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Lightbox></Lightbox>
|
||||
<HelpDialog :show="showHelp" @close="showHelp = false"></HelpDialog>
|
||||
|
||||
<b-card v-if="uiLoading">
|
||||
<Preloader></Preloader>
|
||||
</b-card>
|
||||
|
||||
<b-card v-show="!uiLoading" id="search-panel">
|
||||
<SearchBar @show-help="showHelp=true"></SearchBar>
|
||||
<b-row>
|
||||
<b-col style="height: 70px;" sm="6">
|
||||
<SizeSlider></SizeSlider>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<PathTree @search="search(true)"></PathTree>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col sm="6">
|
||||
<b-row>
|
||||
<b-col style="height: 70px;">
|
||||
<DateSlider></DateSlider>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<IndexPicker></IndexPicker>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<b-tabs>
|
||||
<b-tab :title="$t('mimeTypes')">
|
||||
<MimePicker></MimePicker>
|
||||
</b-tab>
|
||||
<b-tab :title="$t('tags')">
|
||||
<TagPicker></TagPicker>
|
||||
</b-tab>
|
||||
</b-tabs>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-card>
|
||||
|
||||
<Preloader v-if="searchBusy && docs.length === 0" class="mt-3"></Preloader>
|
||||
|
||||
<div v-else-if="docs.length > 0">
|
||||
<ResultsCard></ResultsCard>
|
||||
|
||||
<DocCardWall v-if="optDisplay==='grid'" :docs="docs" :append="appendFunc"></DocCardWall>
|
||||
<DocList v-else :docs="docs" :append="appendFunc"></DocList>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Preloader from "@/components/Preloader.vue";
|
||||
import {mapGetters, mapMutations} from "vuex";
|
||||
import sist2 from "../Sist2Api";
|
||||
import Sist2Api, {EsHit, EsResult} from "../Sist2Api";
|
||||
import SearchBar from "@/components/SearchBar.vue";
|
||||
import IndexPicker from "@/components/IndexPicker.vue";
|
||||
import Vue from "vue";
|
||||
import Sist2Query from "@/Sist2Query";
|
||||
import _debounce from "lodash/debounce";
|
||||
import DocCardWall from "@/components/DocCardWall.vue";
|
||||
import Lightbox from "@/components/Lightbox.vue";
|
||||
import LightboxCaption from "@/components/LightboxCaption.vue";
|
||||
import MimePicker from "../components/MimePicker.vue";
|
||||
import ResultsCard from "@/components/ResultsCard.vue";
|
||||
import PathTree from "@/components/PathTree.vue";
|
||||
import SizeSlider from "@/components/SizeSlider.vue";
|
||||
import DateSlider from "@/components/DateSlider.vue";
|
||||
import TagPicker from "@/components/TagPicker.vue";
|
||||
import DocList from "@/components/DocList.vue";
|
||||
import HelpDialog from "@/components/HelpDialog.vue";
|
||||
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
HelpDialog,
|
||||
DocList,
|
||||
TagPicker,
|
||||
DateSlider,
|
||||
SizeSlider, PathTree, ResultsCard, MimePicker, Lightbox, DocCardWall, IndexPicker, SearchBar, Preloader
|
||||
},
|
||||
data: () => ({
|
||||
loading: false,
|
||||
uiLoading: true,
|
||||
search: undefined as any,
|
||||
docs: [] as EsHit[],
|
||||
docIds: new Set(),
|
||||
searchBusy: false,
|
||||
Sist2Query: Sist2Query,
|
||||
showHelp: false
|
||||
}),
|
||||
computed: {
|
||||
...mapGetters(["indices", "optDisplay"]),
|
||||
},
|
||||
mounted() {
|
||||
this.search = _debounce(async (clear: boolean) => {
|
||||
if (clear) {
|
||||
await this.clearResults();
|
||||
}
|
||||
|
||||
await this.searchNow(Sist2Query.searchQuery());
|
||||
|
||||
}, 350, {leading: false});
|
||||
|
||||
Sist2Api.getMimeTypes().then(mimeMap => {
|
||||
this.$store.commit("setUiMimeMap", mimeMap);
|
||||
});
|
||||
|
||||
this.$store.dispatch("loadFromArgs", this.$route).then(() => {
|
||||
this.$store.subscribe(() => this.$store.dispatch("updateArgs", this.$router));
|
||||
this.$store.subscribe((mutation) => {
|
||||
if ([
|
||||
"setSizeMin", "setSizeMax", "setDateMin", "setDateMax", "setSearchText", "setPathText",
|
||||
"setSortMode", "setOptHighlight", "setOptFragmentSize", "setFuzzy", "setSize", "setSelectedIndices",
|
||||
"setSelectedMimeTypes", "setSelectedTags", "setOptQueryMode", "setOptSearchInPath",
|
||||
].includes(mutation.type)) {
|
||||
if (this.searchBusy) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.search(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
this.getDateRange().then((range: { min: number, max: number }) => {
|
||||
this.setDateBoundsMin(range.min);
|
||||
this.setDateBoundsMax(range.max);
|
||||
|
||||
sist2.getSist2Info().then(data => {
|
||||
this.setSist2Info(data);
|
||||
this.setIndices(data.indices);
|
||||
this.uiLoading = false;
|
||||
|
||||
this.search(true);
|
||||
}).catch(() => {
|
||||
this.showErrorToast();
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
setSist2Info: "setSist2Info",
|
||||
setIndices: "setIndices",
|
||||
setDateBoundsMin: "setDateBoundsMin",
|
||||
setDateBoundsMax: "setDateBoundsMax",
|
||||
setTags: "setTags",
|
||||
}),
|
||||
showErrorToast() {
|
||||
this.$bvToast.toast(
|
||||
this.$t("toast.esConnErr"),
|
||||
{
|
||||
title: this.$t("toast.esConnErrTitle"),
|
||||
noAutoHide: true,
|
||||
toaster: "b-toaster-bottom-right",
|
||||
headerClass: "toast-header-error",
|
||||
bodyClass: "toast-body-error",
|
||||
});
|
||||
},
|
||||
showSyntaxErrorToast: function (): void {
|
||||
this.$bvToast.toast(
|
||||
this.$t("toast.esQueryErr"),
|
||||
{
|
||||
title: this.$t("toast.esQueryErrTitle"),
|
||||
noAutoHide: true,
|
||||
toaster: "b-toaster-bottom-right",
|
||||
headerClass: "toast-header-warning",
|
||||
bodyClass: "toast-body-warning",
|
||||
});
|
||||
},
|
||||
async searchNow(q: any) {
|
||||
this.searchBusy = true;
|
||||
await this.$store.dispatch("incrementQuerySequence");
|
||||
|
||||
Sist2Api.esQuery(q).then(async (resp: EsResult) => {
|
||||
await this.handleSearch(resp);
|
||||
this.searchBusy = false;
|
||||
}).catch(err => {
|
||||
if (err.response.status === 500 && this.$store.state.optQueryMode === "advanced") {
|
||||
this.showSyntaxErrorToast();
|
||||
} else {
|
||||
this.showErrorToast();
|
||||
}
|
||||
});
|
||||
},
|
||||
async clearResults() {
|
||||
this.docs = [];
|
||||
this.docIds.clear();
|
||||
await this.$store.dispatch("clearResults");
|
||||
this.$store.commit("setUiReachedScrollEnd", false);
|
||||
},
|
||||
async handleSearch(resp: EsResult) {
|
||||
if (resp.hits.hits.length == 0) {
|
||||
this.$store.commit("setUiReachedScrollEnd", true);
|
||||
}
|
||||
|
||||
resp.hits.hits = resp.hits.hits.filter(hit => !this.docIds.has(hit._id));
|
||||
resp.hits.hits.forEach(hit => this.docIds.add(hit._id));
|
||||
|
||||
for (const hit of resp.hits.hits) {
|
||||
if (hit._props.isPlayableImage || hit._props.isPlayableVideo) {
|
||||
hit._seq = await this.$store.dispatch("getKeySequence");
|
||||
this.$store.commit("addLightboxSource", {
|
||||
source: `f/${hit._id}`,
|
||||
thumbnail: hit._props.hasThumbnail
|
||||
? `t/${hit._source.index}/${hit._id}`
|
||||
: null,
|
||||
caption: {
|
||||
component: LightboxCaption,
|
||||
props: {hit: hit}
|
||||
},
|
||||
type: hit._props.isVideo ? "video" : "image"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await this.$store.dispatch("remountLightbox");
|
||||
this.$store.commit("setLastQueryResult", resp);
|
||||
|
||||
this.docs.push(...resp.hits.hits);
|
||||
},
|
||||
getDateRange(): Promise<{ min: number, max: number }> {
|
||||
return sist2.esQuery({
|
||||
// TODO: filter current selected indices
|
||||
aggs: {
|
||||
dateMin: {min: {field: "mtime"}},
|
||||
dateMax: {max: {field: "mtime"}},
|
||||
},
|
||||
size: 0
|
||||
}).then(res => {
|
||||
return {
|
||||
min: res.aggregations.dateMin.value,
|
||||
max: res.aggregations.dateMax.value,
|
||||
}
|
||||
})
|
||||
},
|
||||
appendFunc() {
|
||||
if (!this.$store.state.uiReachedScrollEnd && this.search && !this.searchBusy) {
|
||||
this.searchNow(Sist2Query.searchQuery());
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
if (this.$store.state.uiLightboxIsOpen) {
|
||||
this.$store.commit("_setUiShowLightbox", false);
|
||||
next(false);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
#search-panel {
|
||||
box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .08) !important;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.toast-header-error, .toast-body-error {
|
||||
background: #a94442;
|
||||
color: #f2dede !important;
|
||||
}
|
||||
|
||||
.toast-header-error {
|
||||
color: #fff !important;
|
||||
border-bottom: none;
|
||||
margin-bottom: -1em;
|
||||
}
|
||||
|
||||
.toast-header-error .close {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.toast-header-warning, .toast-body-warning {
|
||||
background: #FF8F00;
|
||||
color: #FFF3E0 !important;
|
||||
}
|
||||
</style>
|
||||
79
sist2-vue/src/views/StatsPage.vue
Normal file
79
sist2-vue/src/views/StatsPage.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<b-container>
|
||||
|
||||
<b-card v-if="loading">
|
||||
<Preloader></Preloader>
|
||||
</b-card>
|
||||
|
||||
<template v-else>
|
||||
<b-card>
|
||||
<b-card-body>
|
||||
<b-select v-model="selectedIndex" :options="indexOptions">
|
||||
<template #first>
|
||||
<b-form-select-option :value="null" disabled>{{ $t("indexPickerPlaceholder") }}</b-form-select-option>
|
||||
</template>
|
||||
</b-select>
|
||||
</b-card-body>
|
||||
</b-card>
|
||||
|
||||
<b-card v-if="selectedIndex !== null" class="mt-3">
|
||||
<b-card-body>
|
||||
<D3Treemap :index-id="selectedIndex"></D3Treemap>
|
||||
|
||||
|
||||
</b-card-body>
|
||||
</b-card>
|
||||
|
||||
<b-card v-if="selectedIndex !== null" class="stats-card mt-3">
|
||||
<D3MimeBarCount :index-id="selectedIndex"></D3MimeBarCount>
|
||||
<D3MimeBarSize :index-id="selectedIndex"></D3MimeBarSize>
|
||||
<D3DateHistogram :index-id="selectedIndex"></D3DateHistogram>
|
||||
<D3SizeHistogram :index-id="selectedIndex"></D3SizeHistogram>
|
||||
</b-card>
|
||||
</template>
|
||||
</b-container>
|
||||
</template>
|
||||
<script>
|
||||
import D3Treemap from "@/components/D3Treemap";
|
||||
import Sist2Api from "@/Sist2Api";
|
||||
import Preloader from "@/components/Preloader.vue";
|
||||
import D3MimeBarCount from "@/components/D3MimeBarCount";
|
||||
import D3MimeBarSize from "@/components/D3MimeBarSize";
|
||||
import D3DateHistogram from "@/components/D3DateHistogram";
|
||||
import D3SizeHistogram from "@/components/D3SizeHistogram";
|
||||
|
||||
export default {
|
||||
components: {D3SizeHistogram, D3DateHistogram, D3MimeBarSize, D3MimeBarCount, D3Treemap, Preloader},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
selectedIndex: null,
|
||||
indices: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
indexOptions() {
|
||||
return this.indices.map(idx => {
|
||||
return {
|
||||
text: idx.name,
|
||||
value: idx.id
|
||||
};
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Sist2Api.getSist2Info().then(data => {
|
||||
this.indices = data.indices;
|
||||
this.loading = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
.stats-card {
|
||||
text-align: center;
|
||||
padding: 1em;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user