aboutsummaryrefslogtreecommitdiff
path: root/src-vue/src/views/ThunderstoreModsView.vue
diff options
context:
space:
mode:
authorRémy Raes <contact@remyraes.com>2023-01-14 01:18:48 +0100
committerGitHub <noreply@github.com>2023-01-14 01:18:48 +0100
commit20c3880721cd0f0bd0a2b48a1463b49c514a849b (patch)
tree8bdce436ad295ab550dda3b65f2515c83bec7965 /src-vue/src/views/ThunderstoreModsView.vue
parentbcdab67ee1e0c34dbbf0e6c5d294b8a163ebeeff (diff)
downloadFlightCore-20c3880721cd0f0bd0a2b48a1463b49c514a849b.tar.gz
FlightCore-20c3880721cd0f0bd0a2b48a1463b49c514a849b.zip
refactor: Mods view (#134)
* feat: add UI skeleton for new mods interface * fix: only apply app menu style to app menu items * feat: add menu skeleton * feat: add thunderstore mods view into mods view * refactor: remove thunderstore mods view from router + menu bar * refactor: move search input into mods view * fix: adjust ts mods container padding * refactor: center pagination components * refactor: rework media queries to adapt cards container width * fix: set mods view navigation min-width * refactor: compute mods container width with CSS variables * refactor: remove horizontal padding around ts mods container This will allow them to take much screen space. * feat: Thunderstore mods container is larger * feat: add layouts for 5 to 8 Thunderstore mod columns * feat: add some space to separate navigation menu subparts * fix: move search pagination reset in ThunderstoreModsView component * feat: retrieve Thunderstore mod categories when fetching mods * feat: add mod categories selector component * feat: mod categories selector now filters Thunderstore mods * fix: reset pagination index if needed when selecting mod categories * fix: first mod does not appear anymore while selecting any mod category First mod's categories array was used as an accumulator (in a reduce call) to regroup all mod categories; we now use an empty array as initial value for the accumulator. * feat: add a selector component to sort mods * feat: set sort selector default value on view mount * fix: set default sorting select value as selected in dropdown list * feat: add date_updated field to ThunderstoreMod type * feat: pass sorting value to ThunderstoreModsView as a prop * feat: mods can be sorted by name and release date * feat: mods can be sorted by most downloaded and top rated * fix: don't display sorting select on local mods view * refactor: remove local mods title * refactor: export local mods view code in dedicated component * refactor: export search value in a search-dedicated store * fix: display "no matching mods" message when no mods match This message was previously displayed only if no mods matched AND search input was not empty; now that we have categories selector, we can have no matching mods with an empty input. * refactor: remove unused input prop * fix: mods can be sorted by rating * refactor: remove unused searchValue computed property * style: adjust SortOptions import * refactor: move selected mod categories into search store module * refactor: move mod sorting into search store module * refactor: export mods menu component to dedicated file * fix: remove compare method initialization * feat: local mods can be filtered with search input * build: add ES2018 lib to typescript compiler options * refactor: remove unused variable * fix: retrieve SortOptions values from string input * refactor: move Thunderstore mods view into dedicated folder * style: add missing trailing newline to SortOptions.d.ts
Diffstat (limited to 'src-vue/src/views/ThunderstoreModsView.vue')
-rw-r--r--src-vue/src/views/ThunderstoreModsView.vue240
1 files changed, 0 insertions, 240 deletions
diff --git a/src-vue/src/views/ThunderstoreModsView.vue b/src-vue/src/views/ThunderstoreModsView.vue
deleted file mode 100644
index 5733d30b..00000000
--- a/src-vue/src/views/ThunderstoreModsView.vue
+++ /dev/null
@@ -1,240 +0,0 @@
-<template>
- <div class="fc-container">
- <div v-if="mods.length === 0" class="fc__changelog__container">
- <el-progress :show-text="false" :percentage="50" :indeterminate="true" />
- </div>
- <el-scrollbar v-else class="container" ref="scrollbar">
- <div class="card-container">
- <!-- Search filters -->
- <div class="filter_container">
- <el-input v-model="input" placeholder="Search" clearable @input="onFilterTextChange" />
- <!-- Message displayed when user is typing in search bar -->
- <div v-if="userIsTyping" class="modMessage search">
- Searching mods...
- </div>
-
- <!-- Pagination -->
- <el-pagination
- v-if="shouldDisplayPagination"
- :currentPage="currentPageIndex + 1"
- layout="prev, pager, next"
- :page-size="modsPerPage"
- :total="modsList.length"
- @current-change="(e: number) => currentPageIndex = e - 1"
- />
- </div>
-
- <!-- Message displayed if no mod matched searched words -->
- <div v-if="filteredMods.length === 0 && input.length !== 0 && !userIsTyping" class="modMessage">
- No matching mod has been found.<br/>
- Try another search!
- </div>
-
- <!-- Mod cards -->
- <thunderstore-mod-card v-for="mod of currentPageMods" v-bind:key="mod.name" :mod="mod" />
- </div>
-
- <!-- Bottom pagination -->
- <div class="card-container">
- <div class="filter_container">
- <el-pagination
- class="fc_bottom__pagination"
- v-if="shouldDisplayPagination"
- :currentPage="currentPageIndex + 1"
- layout="prev, pager, next"
- :page-size="modsPerPage"
- :total="modsList.length"
- @current-change="onBottomPaginationChange"
- />
- </div>
- </div>
- </el-scrollbar>
- </div>
-</template>
-
-<script lang="ts">
-import { defineComponent, ref } from 'vue';
-import { ThunderstoreMod } from "../utils/thunderstore/ThunderstoreMod";
-import ThunderstoreModCard from "../components/ThunderstoreModCard.vue";
-import { ElScrollbar, ScrollbarInstance } from "element-plus";
-
-export default defineComponent({
- name: "ThunderstoreModsView",
- components: {ThunderstoreModCard},
- async mounted() {
- this.$store.commit('fetchThunderstoreMods');
- },
- computed: {
- mods(): ThunderstoreMod[] {
- return this.$store.state.thunderstoreMods;
- },
- filteredMods(): ThunderstoreMod[] {
- if (this.searchValue.length === 0) {
- return this.mods;
- }
-
- return this.mods.filter((mod: ThunderstoreMod) => {
- return mod.name.toLowerCase().includes(this.searchValue)
- || mod.owner.toLowerCase().includes(this.searchValue)
- || mod.versions[0].description.toLowerCase().includes(this.searchValue);
- });
- },
- modsList(): ThunderstoreMod[] {
- return this.input.length !== 0 || this.userIsTyping ? this.filteredMods : this.mods;
- },
- modsPerPage(): number {
- return parseInt(this.$store.state.mods_per_page);
- },
- currentPageMods(): ThunderstoreMod[] {
- // User might want to display all mods on one page.
- const perPageValue = this.modsPerPage != 0 ? this.modsPerPage : this.modsList.length;
-
- const startIndex = this.currentPageIndex * perPageValue;
- const endIndexCandidate = startIndex + perPageValue;
- const endIndex = endIndexCandidate > this.modsList.length ? this.modsList.length : endIndexCandidate;
- return this.modsList.slice(startIndex, endIndex);
- },
- shouldDisplayPagination(): boolean {
- return this.modsPerPage != 0 && this.modsList.length > this.modsPerPage;
- }
- },
- data() {
- return {
- // This is the model for the search input.
- input: '',
- // This is the treated value of search input
- searchValue: '',
-
- modsBeingInstalled: [] as string[],
- userIsTyping: false,
-
- currentPageIndex: 0
- };
- },
- methods: {
- /**
- * This method is called each time search input is modified, and
- * triggered filtered mods recomputing by updating the `searchValue`
- * variable.
- *
- * This converts research string and all researched fields to
- * lower case, to match mods regardless of font case.
- */
- onFilterTextChange(value: string) {
- this.currentPageIndex = 0;
- this.searchValue = value.toLowerCase();
- },
-
- /**
- * This updates current pagination and scrolls view to the top.
- */
- onBottomPaginationChange(index: number) {
- this.currentPageIndex = index - 1;
- (this.$refs.scrollbar as ScrollbarInstance).scrollTo({ top: 0, behavior: 'smooth' });
- }
- }
-});
-</script>
-
-<style scoped>
-.fc__changelog__container {
- padding: 20px 30px;
-}
-
-.el-timeline-item__timestamp {
- color: white !important;
- user-select: none !important;
-}
-
-.search {
- display: inline-block;
- margin: 0 0 0 10px !important;
-}
-
-.modMessage {
- color: white;
- margin: 20px 5px;
-}
-
-.card-container {
- margin: 0 auto;
-}
-
-.fc_bottom__pagination {
- padding-bottom: 20px !important;
- padding-right: 10px;
-}
-
-/* Card container dynamic size */
-@media (max-width: 1000px) {
- .card-container {
- width: 752px;
- }
-}
-
-@media (max-width: 812px) {
- .card-container {
- width: 574px;
- }
-
- .el-pagination {
- float: none;
- margin-top: 5px;
- }
-}
-
-@media (max-width: 624px) {
- .card-container {
- width: 376px;
- }
-}
-
-.filter_container {
- margin-bottom: 10px;
-}
-
-.el-input {
- max-width: 200px;
-}
-
-@media (min-width: 812px) {
- .filter_container {
- margin: 5px auto;
- padding: 0 5px;
- max-width: 1000px;
- }
-
- .el-pagination {
- float: right;
- margin: 0;
- }
-}
-
-@media (min-width: 1000px) {
- .card-container {
- width: 940px;
- }
-
- .el-input {
- max-width: 300px;
- }
-}
-
-@media (min-width: 1188px) {
- .card-container {
- width: 1128px;
- }
-}
-
-@media (min-width: 1376px) {
- .card-container {
- width: 1316px;
- }
-}
-
-@media (min-width: 1565px) {
- .card-container {
- width: 1505px;
- }
-}
-</style>