Skip to content

Commit

Permalink
added remove rom from collection dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
zurdi15 committed Jul 2, 2024
1 parent 23e0a06 commit 50bcd00
Show file tree
Hide file tree
Showing 20 changed files with 478 additions and 89 deletions.
12 changes: 6 additions & 6 deletions backend/endpoints/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,18 @@ async def update_collection(request: Request, id: int) -> MessageResponse:
if not collection:
raise CollectionNotFoundInDatabaseException(id)

roms = collection.roms # Default to the roms list from the database

if "roms" in data:
try:
try:
roms = json.loads(data.get("roms"))
roms = json.loads(data["roms"])
except json.JSONDecodeError:
raise ValueError("Invalid JSON for roms field")
raise ValueError("Invalid list for roms field in update collection")

Check failure on line 104 in backend/endpoints/collections.py

View check run for this annotation

Trunk.io / Trunk Check

ruff(B904)

[new] Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling

Check failure on line 104 in backend/endpoints/collections.py

View workflow job for this annotation

GitHub Actions / Trunk Check

ruff(B904)

[new] Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
except KeyError:
roms = collection.roms

cleaned_data = {
"name": data.get("name", collection.name),
"description": data.get("description", collection.description),
"roms": roms,
"roms": list(set(roms)),
"is_public": data.get("is_public", collection.is_public),
"user_id": request.user.id,
}
Expand Down
1 change: 1 addition & 0 deletions backend/endpoints/responses/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class CollectionSchema(BaseModel):
description: str
path_cover_l: str | None
path_cover_s: str | None
has_cover: bool
url_cover: str
roms: set[int]
rom_count: int
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/__generated__/models/CollectionSchema.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 27 additions & 12 deletions frontend/src/components/Gallery/FabOverlay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -118,35 +118,50 @@ function onDownload() {
</v-btn>
<v-btn
key="2"
v-if="auth.scopes.includes('roms.write')"
color="terciary"
elevation="8"
icon
icon="mdi-magnify-scan"
size="default"
@click="onDownload"
>
<v-icon>mdi-download</v-icon>
</v-btn>
@click="onScan"
/>
<v-btn
key="3"
v-if="auth.scopes.includes('roms.write')"
color="terciary"
elevation="8"
icon
icon="mdi-download"
size="default"
@click="onScan"
>
<v-icon>mdi-magnify-scan</v-icon>
</v-btn>
@click="onDownload"
/>
<v-btn
key="4"
color="terciary"
elevation="8"
:icon="
$route.name == 'platform'
? 'mdi-bookmark-plus'
: 'mdi-bookmark-remove'
"
size="default"
@click.stop="
$route.name == 'platform'
? emitter?.emit('showAddToCollectionDialog', romsStore.selectedRoms)
: emitter?.emit(
'showRemoveFromCollectionDialog',
romsStore.selectedRoms
)
"
/>
<v-btn
key="5"
color="terciary"
elevation="8"
icon="mdi-select-all"
size="default"
@click.stop="selectAllRoms"
/>
<v-btn
key="5"
key="6"
color="terciary"
elevation="8"
icon="mdi-select"
Expand Down
197 changes: 197 additions & 0 deletions frontend/src/components/common/Collection/Dialog/AddRoms.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
<script setup lang="ts">
import RAvatarCollection from "@/components/common/Collection/RAvatar.vue";
import RAvatarRom from "@/components/common/Game/RAvatar.vue";
import RDialog from "@/components/common/RDialog.vue";
import type { UpdateCollection } from "@/services/api/collection";
import collectionApi from "@/services/api/collection";
import storeCollections from "@/stores/collections";
import { type SimpleRom } from "@/stores/roms";
import type { Events } from "@/types/emitter";
import type { Emitter } from "mitt";
import { inject, ref, watch } from "vue";
import { useDisplay, useTheme } from "vuetify";
// Props
const theme = useTheme();
const { mdAndUp } = useDisplay();
const show = ref(false);
const collectionsStore = storeCollections();
const selectedCollection = ref<UpdateCollection>();
const roms = ref<SimpleRom[]>([]);
const emitter = inject<Emitter<Events>>("emitter");
emitter?.on("showAddToCollectionDialog", (romsToAdd) => {
roms.value = romsToAdd;
updateDataTablePages();
show.value = true;
});
const HEADERS = [
{
title: "Name",
align: "start",
sortable: true,
key: "name",
},
] as const;
const page = ref(1);
const itemsPerPage = ref(10);
const pageCount = ref(0);
const PER_PAGE_OPTIONS = [10, 25, 50, 100];
// Functions
async function addRomsToCollection() {
if (!selectedCollection.value) return;
selectedCollection.value.roms.push(...roms.value.map((r) => r.id));
await collectionApi
.updateCollection({ collection: selectedCollection.value })
.then(({ data }) => {
emitter?.emit("snackbarShow", {
msg: `Roms added to ${selectedCollection.value?.name} successfully!`,
icon: "mdi-check-bold",
color: "green",
timeout: 2000,
});
})
.catch((error) => {
console.log(error);
emitter?.emit("snackbarShow", {
msg: error.response.data.detail,
icon: "mdi-close-circle",
color: "red",
});
return;
})
.finally(() => {
emitter?.emit("showLoadingDialog", { loading: false, scrim: false });
closeDialog();
});
}
function updateDataTablePages() {
pageCount.value = Math.ceil(roms.value.length / itemsPerPage.value);
}
watch(itemsPerPage, async () => {
updateDataTablePages();
});
function closeDialog() {
roms.value = [];
show.value = false;
selectedCollection.value = undefined;
}
</script>

<template>
<r-dialog
@close="closeDialog"
v-model="show"
icon="mdi-bookmark-plus-outline"
scroll-content
:width="mdAndUp ? '45vw' : '95vw'"
>
<template #header>
<v-row no-gutters class="justify-center">
<span>Adding</span>
<span class="text-romm-accent-1 mx-1">{{ roms.length }}</span>
<span>games to collection</span>
</v-row>
</template>
<template #prepend>
<v-select
v-model="selectedCollection"
class="pa-3"
density="default"
label="Collection"
item-title="name"
:items="collectionsStore.all"
variant="outlined"
hide-details
return-object
clearable
>
<template #item="{ props, item }">
<v-list-item
class="py-4"
v-bind="props"
:title="item.raw.name ?? ''"
:subtitle="item.raw.description"
>
<template #prepend>
<r-avatar-collection :collection="item.raw" />
</template>
<template #append>
<v-chip class="ml-2" size="x-small" label>
{{ item.raw.rom_count }}
</v-chip>
</template>
</v-list-item>
</template>
</v-select>
</template>
<template #content>
<v-data-table
:item-value="(item) => item.id"
:items="roms"
:width="mdAndUp ? '60vw' : '95vw'"
:items-per-page="itemsPerPage"
:items-per-page-options="PER_PAGE_OPTIONS"
:headers="HEADERS"
v-model:page="page"
hide-default-header
>
<template #item.name="{ item }">
<v-list-item class="px-0">
<template #prepend>
<r-avatar-rom :rom="item" />
</template>
<v-row no-gutters
><v-col>{{ item.name }}</v-col></v-row
>
</v-list-item>
</template>
<template #bottom>
<v-divider />
<v-row no-gutters class="pt-2 align-center justify-center">
<v-col class="px-6">
<v-pagination
v-model="page"
rounded="0"
:show-first-last-page="true"
active-color="romm-accent-1"
:length="pageCount"
/>
</v-col>
<v-col cols="5" sm="3">
<v-select
v-model="itemsPerPage"
class="pa-2"
label="Roms per page"
density="compact"
variant="outlined"
:items="PER_PAGE_OPTIONS"
hide-details
/>
</v-col>
</v-row>
</template>
</v-data-table>
</template>
<template #append>
<v-row class="justify-center my-2">
<v-btn-group divided density="compact">
<v-btn class="bg-terciary" @click="closeDialog" variant="flat">
Cancel
</v-btn>
<v-btn
class="bg-terciary text-romm-green"
:disabled="!selectedCollection"
:variant="!selectedCollection ? 'plain' : 'flat'"
@click="addRomsToCollection"
>
Confirm
</v-btn>
</v-btn-group>
</v-row>
</template>
</r-dialog>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,12 @@ function closeDialog() {
<v-row class="justify-center MT-4 mb-2" no-gutters>
<v-btn-group divided density="compact">
<v-btn class="bg-terciary" @click="closeDialog"> Cancel </v-btn>
<v-btn class="text-romm-green bg-terciary" @click="createCollection">
<v-btn
class="bg-terciary text-romm-green"
:disabled="!collection.name"
:variant="!collection.name ? 'plain' : 'flat'"
@click="createCollection"
>
Create
</v-btn>
</v-btn-group>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<script setup lang="ts">
import RDialog from "@/components/common/RDialog.vue";
import CollectionCard from "@/components/common/Collection/Card.vue";
import collectionApi, {
type UpdateCollection,
} from "@/services/api/collection";
import storeCollections, { type Collection } from "@/stores/collections";
import RDialog from "@/components/common/RDialog.vue";
import collectionApi from "@/services/api/collection";
import type { UpdateCollection } from "@/services/api/collection";
import { type Collection } from "@/stores/collections";
import type { Events } from "@/types/emitter";
import type { Emitter } from "mitt";
import { inject, ref } from "vue";
Expand Down Expand Up @@ -127,7 +126,12 @@ function closeDialog() {
<v-col>
<v-row class="pa-2 justify-center" no-gutters>
<v-col class="cover">
<collection-card :show-title="false" :with-link="false" :collection="collection" :src="imagePreviewUrl">
<collection-card
:show-title="false"
:with-link="false"
:collection="collection"
:src="imagePreviewUrl"
>
<template #append-inner>
<v-chip-group class="pa-0">
<v-chip
Expand Down
Loading

0 comments on commit 50bcd00

Please sign in to comment.