mirror of
https://github.com/romancm/gamebrary
synced 2024-11-12 22:47:14 +00:00
Improve button styles, improve tags page layout, improve delete account UX
This commit is contained in:
parent
a431e332f6
commit
57160194a9
17 changed files with 147 additions and 116 deletions
|
@ -41,7 +41,7 @@
|
|||
|
||||
<b-button-group class="mb-3">
|
||||
<b-button v-for="{ text, value } in $options.BOARD_TYPES" :key="value"
|
||||
:variant="value === board.type ? 'primary' : 'white'" @click="board.type = value">
|
||||
:variant="value === board.type ? 'black' : 'white'" @click="board.type = value">
|
||||
{{ text }}
|
||||
</b-button>
|
||||
</b-button-group>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<template #default="{ hide }">
|
||||
<SidebarHeader @hide="hide" title="Edit tag" />
|
||||
|
||||
<form @submit.prevent="saveTag" class="p-3">
|
||||
<form @submit.prevent="saveTag" class="px-3">
|
||||
<div class="d-flex">
|
||||
<b-form-input
|
||||
id="tagName"
|
||||
|
|
|
@ -132,7 +132,7 @@ export default {
|
|||
return this.darkTheme ? 'light' : 'secondary';
|
||||
}
|
||||
|
||||
return this.darkTheme ? 'outline-light' : 'outline-secondary';
|
||||
return this.darkTheme ? 'outline-light' : 'secondary';
|
||||
},
|
||||
|
||||
draggingDisabled() {
|
||||
|
|
|
@ -139,7 +139,7 @@ export default {
|
|||
},
|
||||
|
||||
activeVariant() {
|
||||
return this.darkTheme ? 'success' : 'primary';
|
||||
return this.darkTheme ? 'success' : 'black';
|
||||
},
|
||||
|
||||
gameCount() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template lang="html">
|
||||
<b-modal
|
||||
id="deleteAccount"
|
||||
no-close-on-backdrop
|
||||
id="delete-account-modal"
|
||||
:no-close-on-backdrop="deleting"
|
||||
:header-bg-variant="darkTheme ? 'dark' : 'transparent'"
|
||||
:header-text-variant="darkTheme ? 'white' : 'dark'"
|
||||
:body-bg-variant="darkTheme ? 'dark' : 'transparent'"
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
<b-link
|
||||
class="mb-2 text-danger px-3 py-2"
|
||||
v-b-modal.deleteAccount
|
||||
@click="openDeleteAccountSidebar"
|
||||
>
|
||||
Delete account
|
||||
</b-link>
|
||||
|
@ -207,6 +207,11 @@ export default {
|
|||
this.saving = false;
|
||||
});
|
||||
},
|
||||
|
||||
openDeleteAccountSidebar() {
|
||||
this.$root.$emit('bv::toggle::collapse', 'settings-sidebar');
|
||||
this.$bvModal.show('delete-account-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -10,23 +10,22 @@
|
|||
/>
|
||||
|
||||
<b-button
|
||||
:disabled="outOfSpace"
|
||||
title=""
|
||||
:variant="darkTheme ? 'success' : 'primary'"
|
||||
v-bind="buttonProps"
|
||||
@click="triggerFileUpload"
|
||||
>
|
||||
<b-spinner small v-if="saving" />
|
||||
<i v-else class="fa-regular fa-upload" />
|
||||
<span v-if="saving">
|
||||
<b-spinner small class="mr-2" />
|
||||
Uploading
|
||||
</span>
|
||||
|
||||
<span v-if="!saving">
|
||||
<i class="fa-regular fa-upload mr-2" />
|
||||
Upload
|
||||
</span>
|
||||
|
||||
<slot />
|
||||
</b-button>
|
||||
|
||||
<b-alert
|
||||
v-if="isDuplicate && !saving && file && file.name"
|
||||
show
|
||||
variant="warning"
|
||||
>
|
||||
{{ $t('wallpapers.form.duplicateMessage', { fileName: file.name }) }}
|
||||
</b-alert>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -44,25 +43,19 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapState(['wallpapers']),
|
||||
...mapGetters(['darkTheme']),
|
||||
...mapGetters(['darkTheme', 'buttonProps']),
|
||||
|
||||
isDuplicate() {
|
||||
const { file, existingFiles } = this;
|
||||
// spaceUsed() {
|
||||
// return this.wallpapers.reduce((total, { metadata }) => {
|
||||
// const size = metadata?.size || 0;
|
||||
|
||||
return existingFiles?.includes(file?.name);
|
||||
},
|
||||
// return total + size;
|
||||
// }, 0);
|
||||
// },
|
||||
|
||||
spaceUsed() {
|
||||
return this.wallpapers.reduce((total, { metadata }) => {
|
||||
const size = metadata?.size || 0;
|
||||
|
||||
return total + size;
|
||||
}, 0);
|
||||
},
|
||||
|
||||
outOfSpace() {
|
||||
return this.spaceUsed >= this.maxSpace;
|
||||
},
|
||||
// outOfSpace() {
|
||||
// return this.spaceUsed >= this.maxSpace;
|
||||
// },
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -71,9 +64,8 @@ export default {
|
|||
},
|
||||
|
||||
async uploadWallpaper() {
|
||||
if (this.isDuplicate) return this.$bvToast.toast('File already exists', { variant: 'warning' });
|
||||
if (!this.file) return false;
|
||||
|
||||
|
||||
this.saving = true;
|
||||
|
||||
try {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<SidebarHeader @hide="hide" title="Filter search results" />
|
||||
|
||||
<div
|
||||
class="p-3"
|
||||
class="px-3"
|
||||
>
|
||||
<a :href="wallpaperUrl" target="_blank">
|
||||
<b-img
|
||||
|
@ -20,32 +20,24 @@
|
|||
</a>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-between pb-2">
|
||||
<a :href="wallpaperUrl" target="_blank">
|
||||
<a :href="wallpaperUrl" target="_blank" class="text-truncate">
|
||||
{{ activeWallpaper.name }}
|
||||
</a>
|
||||
|
||||
<div>
|
||||
<!-- <i class="fa-solid fa-file-png fa-fw" /> -->
|
||||
<!-- {{ activeWallpaper.size }} -->
|
||||
<!-- {{ activeWallpaper.timeCreated }} -->
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-between pb-2">
|
||||
<b-button
|
||||
v-b-modal.deleteConfirm
|
||||
variant="danger"
|
||||
class="ml-2"
|
||||
v-b-tooltip.hover="{ title: 'Delete wallpaper', placement: 'bottom', boundary: 'viewports' }"
|
||||
>
|
||||
<i class="fa fa-trash" aria-hidden="true" />
|
||||
</b-button>
|
||||
</div>
|
||||
<b-button
|
||||
v-b-modal.deleteConfirm
|
||||
variant="danger"
|
||||
class="ml-2"
|
||||
v-b-tooltip.hover="{ title: 'Delete wallpaper', placement: 'bottom', boundary: 'viewports' }"
|
||||
>
|
||||
<i class="fa fa-trash" aria-hidden="true" />
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<b-button
|
||||
v-b-toggle.boards-list
|
||||
title=""
|
||||
variant="primary"
|
||||
v-bind="buttonProps"
|
||||
v-b-tooltip.hover.bottom
|
||||
>
|
||||
Set as wallpaper
|
||||
|
@ -125,7 +117,7 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapState(['boards', 'wallpapers', 'activeWallpaper']),
|
||||
...mapGetters(['darkTheme', 'sidebarRightProps']),
|
||||
...mapGetters(['darkTheme', 'sidebarRightProps', 'buttonProps']),
|
||||
|
||||
formattedBoards() {
|
||||
return this.boards.map((board) => ({ ...board, backgroundUrl: this.getWallpaperUrl(board.backgroundUrl) }));
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template lang="html">
|
||||
<b-list-group>
|
||||
<b-list-group-item
|
||||
v-for="wallpaper in sortedWallpapers"
|
||||
v-for="(wallpaper, index) in sortedWallpapers"
|
||||
:variant="darkTheme ? 'dark' : 'light'"
|
||||
:key="wallpaper.name"
|
||||
:key="index"
|
||||
button
|
||||
@click="handleClick(wallpaper)"
|
||||
>
|
||||
|
|
|
@ -35,9 +35,9 @@ Vue.use(VueI18n);
|
|||
// Component specific defaults are keyed by their PascalCase name with the props as camelCase properties.
|
||||
// https://bootstrap-vue.org/docs/reference/settings#settings
|
||||
Vue.use(BootstrapVue, {
|
||||
BButton: { variant: 'secondary' },
|
||||
BButton: { variant: 'black' },
|
||||
BAvatar: { variant: 'muted' },
|
||||
BDropdown: { variant: 'primary' },
|
||||
BDropdown: { variant: 'black' },
|
||||
BToast: {
|
||||
noCloseButton: true,
|
||||
},
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
|
||||
<portal to="pageTitle">
|
||||
<div class="d-flex flex-column">
|
||||
<h3 :class="['text-truncate', { 'text-white': backgroundUrl && darkTheme }]" :style="publicUserName ? 'line-height: 1rem' : ''">
|
||||
{{ board.name }}
|
||||
</h3>
|
||||
|
||||
<b-link
|
||||
v-if="publicUserName"
|
||||
style="font-size: 12px"
|
||||
|
@ -33,12 +29,15 @@
|
|||
|
||||
<portal to="headerActions">
|
||||
<b-dropdown
|
||||
:variant="darkTheme ? 'black' : 'light'"
|
||||
v-if="user"
|
||||
variant="black"
|
||||
right
|
||||
no-caret
|
||||
>
|
||||
<template #button-content>
|
||||
<i class="fa-solid fa-ellipsis-vertical px-1" />
|
||||
{{ board.name }}
|
||||
|
||||
<i class="fa-regular fa-caret-down fa-fw" />
|
||||
</template>
|
||||
|
||||
<b-dropdown-item v-if="canEdit" v-b-toggle.edit-board-sidebar>
|
||||
|
@ -49,6 +48,13 @@
|
|||
<i class="fa-regular fa-clone fa-fw" /> Clone board
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
|
||||
<b-button
|
||||
v-else
|
||||
variant="black"
|
||||
>
|
||||
{{ board.name }}
|
||||
</b-button>
|
||||
</portal>
|
||||
|
||||
<StandardBoard v-if="board.type === $options.BOARD_TYPE_STANDARD" />
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
<portal v-if="!this.loading && !isEmpty && user" to="headerActions">
|
||||
<b-button
|
||||
title="Create board"
|
||||
:variant="darkTheme ? 'success' : 'primary'"
|
||||
:variant="darkTheme ? 'success' : 'black'"
|
||||
v-b-toggle.create-board-sidebar
|
||||
>
|
||||
<i class="fa-solid fa-plus" />
|
||||
Create board
|
||||
</b-button>
|
||||
</portal>
|
||||
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
<portal to="headerActions">
|
||||
<b-dropdown
|
||||
v-if="game && user"
|
||||
:variant="darkTheme ? 'black' : 'light'"
|
||||
no-caret
|
||||
:variant="darkTheme ? 'success' : 'black'"
|
||||
>
|
||||
<template #button-content>
|
||||
<i class="fa-solid fa-ellipsis-vertical px-1" />
|
||||
{{ gameName }}
|
||||
</template>
|
||||
|
||||
<b-dropdown-item
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
<b-button
|
||||
title="Add games"
|
||||
v-b-tooltip.hover
|
||||
:variant="darkTheme ? 'success' : 'primary'"
|
||||
v-bind="buttonProps"
|
||||
@click="addGame"
|
||||
>
|
||||
<i class="fa-solid fa-plus" />
|
||||
Add games
|
||||
</b-button>
|
||||
</portal>
|
||||
|
||||
|
@ -78,7 +79,7 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapState(['games', 'cachedGames', 'user', 'progresses']),
|
||||
...mapGetters(['darkTheme', 'navPosition']),
|
||||
...mapGetters(['darkTheme', 'navPosition', 'buttonProps']),
|
||||
|
||||
likedGames() {
|
||||
if (!this.user) return null;
|
||||
|
|
|
@ -4,18 +4,26 @@
|
|||
|
||||
<portal v-if="user && !isEmpty" to="headerActions">
|
||||
<b-button
|
||||
title="Add games"
|
||||
title="Add note"
|
||||
v-b-tooltip.hover
|
||||
:variant="darkTheme ? 'success' : 'primary'"
|
||||
v-bind="buttonProps"
|
||||
@click="openGameSelectorSidebar"
|
||||
>
|
||||
<i class="fa-solid fa-plus" />
|
||||
Add note
|
||||
</b-button>
|
||||
</portal>
|
||||
|
||||
<b-spinner v-if="loading" class="spinner-centered" />
|
||||
|
||||
<template v-else>
|
||||
<b-form-input
|
||||
type="search"
|
||||
class="mb-3"
|
||||
placeholder="Search notes"
|
||||
v-model="searchText"
|
||||
/>
|
||||
|
||||
<EmptyState
|
||||
v-if="isEmpty"
|
||||
illustration="notes"
|
||||
|
@ -38,46 +46,43 @@
|
|||
illustration="notes"
|
||||
message="No results"
|
||||
>
|
||||
<b-button @click="searchText = ''">
|
||||
<b-button
|
||||
@click="searchText = ''"
|
||||
v-bind="buttonProps"
|
||||
>
|
||||
Clear search
|
||||
</b-button>
|
||||
</EmptyState>
|
||||
|
||||
<template v-else>
|
||||
<b-form-input
|
||||
type="search"
|
||||
class="mb-3 mt-2"
|
||||
placeholder="Search notes"
|
||||
v-model="searchText"
|
||||
/>
|
||||
|
||||
<b-card
|
||||
<b-media
|
||||
v-for="({ note, game }, index) in filteredNotes"
|
||||
body-class="p-3"
|
||||
:bg-variant="darkTheme ? 'dark' : 'light'"
|
||||
:text-variant="darkTheme ? 'light' : 'dark'"
|
||||
:key="index"
|
||||
class="cursor-pointer mb-2"
|
||||
@click="openNote(game.id)"
|
||||
vertical-align="center"
|
||||
>
|
||||
<b-card-text v-if="game">
|
||||
<template #aside>
|
||||
<GameCard
|
||||
small
|
||||
:game-id="game.id"
|
||||
selectable
|
||||
@click.native.stop="openNote(game.id)"
|
||||
small
|
||||
hide-notes
|
||||
hide-progress
|
||||
vertical
|
||||
hide-title
|
||||
hide-platforms
|
||||
/>
|
||||
</template>
|
||||
|
||||
<b-alert
|
||||
v-if="note"
|
||||
v-html="note"
|
||||
show
|
||||
class="cursor-pointer mt-3 mb-0"
|
||||
variant="warning"
|
||||
@click.native="$router.push({ name: 'game.notes', params: { id: game.id, slug: game.slug } })"
|
||||
/>
|
||||
</b-card-text>
|
||||
</b-card>
|
||||
<h2>{{ game.name }}</h2>
|
||||
|
||||
<b-alert
|
||||
v-if="note"
|
||||
v-html="note"
|
||||
show
|
||||
class="cursor-pointer mt-3 mb-0"
|
||||
variant="warning"
|
||||
@click.native="$router.push({ name: 'game.notes', params: { id: game.id, slug: game.slug } })"
|
||||
/>
|
||||
</b-media>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
@ -103,7 +108,7 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapState(['notes', 'cachedGames', 'user']),
|
||||
...mapGetters(['darkTheme']),
|
||||
...mapGetters(['darkTheme', 'buttonProps']),
|
||||
|
||||
isEmpty() {
|
||||
return !this.notes || !Object.keys(this.notes)?.length;
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
|
||||
<portal v-if="user && !isEmpty" to="headerActions">
|
||||
<b-button
|
||||
:variant="darkTheme ? 'success' : 'primary'"
|
||||
v-bind="buttonProps"
|
||||
v-b-toggle.create-tag-sidebar
|
||||
title="Add tag"
|
||||
>
|
||||
<i class="fa-solid fa-plus" />
|
||||
Add tag
|
||||
</b-button>
|
||||
</portal>
|
||||
|
||||
|
@ -39,17 +40,38 @@
|
|||
class="flex-column align-items-start"
|
||||
@click="openEditTagSidebar(index)"
|
||||
>
|
||||
<div class="d-flex w-100 justify-content-between align-items-center">
|
||||
<b-button
|
||||
variant="transparent"
|
||||
:style="`background-color: ${bgColor}; color: ${textColor}`"
|
||||
>
|
||||
{{ name }}
|
||||
</b-button>
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<div class="d-flex flex-column">
|
||||
<b-button
|
||||
variant="transparent"
|
||||
:style="`background-color: ${bgColor}; color: ${textColor}`"
|
||||
class="mb-2"
|
||||
>
|
||||
{{ name }}
|
||||
</b-button>
|
||||
|
||||
<b-badge variant="primary" pill>
|
||||
{{ taggedGames.length }} games
|
||||
</b-badge>
|
||||
</div>
|
||||
|
||||
<b-avatar-group>
|
||||
<GameCard
|
||||
v-for="gameId in taggedGames"
|
||||
small
|
||||
slim
|
||||
hide-title
|
||||
vertical
|
||||
hide-platforms
|
||||
hide-tags
|
||||
hide-progress
|
||||
class="ml-n5 border-light border"
|
||||
:key="gameId"
|
||||
:game-id="gameId"
|
||||
/>
|
||||
|
||||
</b-avatar-group>
|
||||
|
||||
<b-badge variant="primary" pill>
|
||||
{{ taggedGames.length }} games
|
||||
</b-badge>
|
||||
</div>
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
|
@ -71,11 +93,13 @@
|
|||
|
||||
<script>
|
||||
import { mapState, mapGetters } from 'vuex';
|
||||
import GameCard from '@/components/GameCard';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EmptyState,
|
||||
GameCard,
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -86,7 +110,7 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapState(['tags', 'user', 'cachedGames', 'activeTagIndex']),
|
||||
...mapGetters(['darkTheme']),
|
||||
...mapGetters(['darkTheme', 'buttonProps']),
|
||||
|
||||
isEmpty() {
|
||||
return this.tags?.length === 0;
|
||||
|
|
|
@ -32,6 +32,12 @@ export default {
|
|||
return game?.websites?.map(({ url, category }) => ({ url, ...LINKS_CATEGORIES[category] })) || [];
|
||||
},
|
||||
|
||||
buttonProps(state, getters) {
|
||||
return {
|
||||
variant: getters?.darkTheme ? 'success' : 'black',
|
||||
}
|
||||
},
|
||||
|
||||
sidebarRightProps(state, getters) {
|
||||
return {
|
||||
scrollable: true,
|
||||
|
|
Loading…
Reference in a new issue