{
@keyup.enter="searchRoms"
@click:clear="searchRoms"
v-model="searchValue"
+ :disabled="searching"
label="Search"
hide-details
class="bg-terciary"
@@ -128,7 +129,7 @@ onBeforeUnmount(() => {
label="Platform"
class="bg-terciary"
item-title="platform_name"
- :disabled="platforms.length == 0"
+ :disabled="platforms.length == 0 || searching"
hide-details
clearable
single-line
diff --git a/frontend/src/components/common/Game/RAvatar.vue b/frontend/src/components/common/Game/RAvatar.vue
index e4a8d0f2c..bdc2c5fe0 100644
--- a/frontend/src/components/common/Game/RAvatar.vue
+++ b/frontend/src/components/common/Game/RAvatar.vue
@@ -1,9 +1,21 @@
-
+
diff --git a/frontend/src/components/common/Game/Table.vue b/frontend/src/components/common/Game/Table.vue
index 2be0d1a15..b0529dcd3 100644
--- a/frontend/src/components/common/Game/Table.vue
+++ b/frontend/src/components/common/Game/Table.vue
@@ -2,7 +2,6 @@
import AdminMenu from "@/components/common/Game/AdminMenu.vue";
import RAvatar from "@/components/common/Game/RAvatar.vue";
import romApi from "@/services/api/rom";
-import storeAuth from "@/stores/auth";
import storeDownload from "@/stores/download";
import storeRoms, { type SimpleRom } from "@/stores/roms";
import type { Events } from "@/types/emitter";
@@ -30,7 +29,6 @@ const router = useRouter();
const route = useRoute();
const downloadStore = storeDownload();
const romsStore = storeRoms();
-const auth = storeAuth();
const page = ref(parseInt(window.location.hash.slice(1)) || 1);
const storedRomsPerPage = parseInt(localStorage.getItem("romsPerPage") ?? "");
const itemsPerPage = ref(isNaN(storedRomsPerPage) ? 25 : storedRomsPerPage);
@@ -120,15 +118,7 @@ onMounted(() => {
-
+
{{ item.name }} {
class="translucent-dark ml-2"
size="x-small"
>
- +{{ item.siblings.length + 1 }}
+ +{{ item.siblings.length }}
@@ -189,11 +179,7 @@ onMounted(() => {
-
+
mdi-dots-vertical
diff --git a/frontend/src/components/common/Navigation/CollectionsBtn.vue b/frontend/src/components/common/Navigation/CollectionsBtn.vue
new file mode 100644
index 000000000..476cad35b
--- /dev/null
+++ b/frontend/src/components/common/Navigation/CollectionsBtn.vue
@@ -0,0 +1,31 @@
+
+
+ mdi-bookmark-box-multiple
+
diff --git a/frontend/src/components/common/Navigation/CollectionsDrawer.vue b/frontend/src/components/common/Navigation/CollectionsDrawer.vue
new file mode 100644
index 000000000..c99ce09b3
--- /dev/null
+++ b/frontend/src/components/common/Navigation/CollectionsDrawer.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+ Add Collection
+
+
+
diff --git a/frontend/src/components/common/Navigation/HomeBtn.vue b/frontend/src/components/common/Navigation/HomeBtn.vue
new file mode 100644
index 000000000..e88bc2158
--- /dev/null
+++ b/frontend/src/components/common/Navigation/HomeBtn.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
diff --git a/frontend/src/components/common/Navigation/MainAppBar.vue b/frontend/src/components/common/Navigation/MainAppBar.vue
new file mode 100644
index 000000000..8cca01e2e
--- /dev/null
+++ b/frontend/src/components/common/Navigation/MainAppBar.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/common/Navigation/MainDrawer.vue b/frontend/src/components/common/Navigation/MainDrawer.vue
new file mode 100644
index 000000000..57137581d
--- /dev/null
+++ b/frontend/src/components/common/Navigation/MainDrawer.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/common/Navigation/PlatformsBtn.vue b/frontend/src/components/common/Navigation/PlatformsBtn.vue
new file mode 100644
index 000000000..6b1fcb34c
--- /dev/null
+++ b/frontend/src/components/common/Navigation/PlatformsBtn.vue
@@ -0,0 +1,28 @@
+
+
+ mdi-controller
+
diff --git a/frontend/src/components/common/Navigation/PlatformsDrawer.vue b/frontend/src/components/common/Navigation/PlatformsDrawer.vue
new file mode 100644
index 000000000..96b04f984
--- /dev/null
+++ b/frontend/src/components/common/Navigation/PlatformsDrawer.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/common/Navigation/ScanBtn.vue b/frontend/src/components/common/Navigation/ScanBtn.vue
new file mode 100644
index 000000000..b3482c616
--- /dev/null
+++ b/frontend/src/components/common/Navigation/ScanBtn.vue
@@ -0,0 +1,126 @@
+
+
+
+
+ mdi-magnify-scan
+
+
diff --git a/frontend/src/components/common/Navigation/SearchBtn.vue b/frontend/src/components/common/Navigation/SearchBtn.vue
new file mode 100644
index 000000000..d29ebc339
--- /dev/null
+++ b/frontend/src/components/common/Navigation/SearchBtn.vue
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/frontend/src/components/common/Navigation/SettingsDrawer.vue b/frontend/src/components/common/Navigation/SettingsDrawer.vue
new file mode 100644
index 000000000..4e6f2bff5
--- /dev/null
+++ b/frontend/src/components/common/Navigation/SettingsDrawer.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ UI Settings
+ Library Management
+
+ Administration
+
+
+ Logout
+
+
+
+
+
+ Logout
+
+
+
+
diff --git a/frontend/src/components/common/Navigation/UploadBtn.vue b/frontend/src/components/common/Navigation/UploadBtn.vue
new file mode 100644
index 000000000..c8ae3d383
--- /dev/null
+++ b/frontend/src/components/common/Navigation/UploadBtn.vue
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/frontend/src/components/common/Navigation/UserBtn.vue b/frontend/src/components/common/Navigation/UserBtn.vue
new file mode 100644
index 000000000..c5b98fda1
--- /dev/null
+++ b/frontend/src/components/common/Navigation/UserBtn.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/common/Platform/Card.vue b/frontend/src/components/common/Platform/Card.vue
index 30aef3983..42a6b74be 100644
--- a/frontend/src/components/common/Platform/Card.vue
+++ b/frontend/src/components/common/Platform/Card.vue
@@ -20,7 +20,7 @@ defineProps<{ platform: Platform }>();
:title="platform.name?.toString()"
class="px-2 text-truncate text-caption"
>
- {{ platform.name }}
+ {{ platform.name }}
diff --git a/frontend/src/components/common/Platform/ListItem.vue b/frontend/src/components/common/Platform/ListItem.vue
index 79cb7baa2..384159ce2 100644
--- a/frontend/src/components/common/Platform/ListItem.vue
+++ b/frontend/src/components/common/Platform/ListItem.vue
@@ -36,7 +36,7 @@ withDefaults(defineProps<{ platform: Platform; rail?: boolean }>(), {
{{ platform.name }}{{ platform.name }}
diff --git a/frontend/src/components/common/Game/Dialog/SearchCoverRom.vue b/frontend/src/components/common/SearchCover.vue
similarity index 70%
rename from frontend/src/components/common/Game/Dialog/SearchCoverRom.vue
rename to frontend/src/components/common/SearchCover.vue
index 4f69673ed..c8c655ca3 100644
--- a/frontend/src/components/common/Game/Dialog/SearchCoverRom.vue
+++ b/frontend/src/components/common/SearchCover.vue
@@ -1,8 +1,7 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/layouts/Dashboard/Recent.vue b/frontend/src/layouts/Dashboard/Recent.vue
index f7a924777..d04327d26 100644
--- a/frontend/src/layouts/Dashboard/Recent.vue
+++ b/frontend/src/layouts/Dashboard/Recent.vue
@@ -1,38 +1,27 @@
{
:xl="views[0]['size-xl']"
>
{
-
diff --git a/frontend/src/layouts/Dashboard/Summary.vue b/frontend/src/layouts/Dashboard/Stats.vue
similarity index 100%
rename from frontend/src/layouts/Dashboard/Summary.vue
rename to frontend/src/layouts/Dashboard/Stats.vue
diff --git a/frontend/src/plugins/pinia.d.ts b/frontend/src/plugins/pinia.d.ts
new file mode 100644
index 000000000..32a722b64
--- /dev/null
+++ b/frontend/src/plugins/pinia.d.ts
@@ -0,0 +1,8 @@
+import "pinia";
+import { Router } from "vue-router";
+
+declare module "pinia" {
+ export interface PiniaCustomProperties {
+ $router: Router;
+ }
+}
diff --git a/frontend/src/plugins/pinia.ts b/frontend/src/plugins/pinia.ts
index b0b380854..4b3a8a582 100644
--- a/frontend/src/plugins/pinia.ts
+++ b/frontend/src/plugins/pinia.ts
@@ -1,5 +1,9 @@
import { createPinia } from "pinia";
+import { markRaw } from "vue";
+import router from "@/plugins/router";
const pinia = createPinia();
-
+pinia.use(({ store }) => {
+ store.$router = markRaw(router);
+});
export default pinia;
diff --git a/frontend/src/plugins/router.ts b/frontend/src/plugins/router.ts
index 62a7269fd..b897e284f 100644
--- a/frontend/src/plugins/router.ts
+++ b/frontend/src/plugins/router.ts
@@ -20,7 +20,12 @@ const routes = [
{
path: "/platform/:platform",
name: "platform",
- component: () => import("@/views/Gallery.vue"),
+ component: () => import("@/views/Gallery/Platform.vue"),
+ },
+ {
+ path: "/collection/:collection",
+ name: "collection",
+ component: () => import("@/views/Gallery/Collection.vue"),
},
{
path: "/rom/:rom",
@@ -69,6 +74,7 @@ const router = createRouter({
router.afterEach(() => {
// Scroll to top to avoid annoying behaviour in mobile
window.scrollTo({ top: 0, left: 0 });
+ // TODO: check permission for views. Ex: view user can access to /scan view
});
export default router;
diff --git a/frontend/src/services/api/collection.ts b/frontend/src/services/api/collection.ts
new file mode 100644
index 000000000..1ee57285f
--- /dev/null
+++ b/frontend/src/services/api/collection.ts
@@ -0,0 +1,68 @@
+import type { MessageResponse } from "@/__generated__";
+import api from "@/services/api/index";
+import type { Collection } from "@/stores/collections";
+
+export type UpdatedCollection = Collection & {
+ artwork?: File;
+ url_cover?: string;
+};
+
+export const collectionApi = api;
+
+async function createCollection({
+ collection,
+}: {
+ collection: UpdatedCollection;
+}): Promise<{ data: Collection }> {
+ const formData = new FormData();
+ formData.append("name", collection.name || "");
+ formData.append("description", collection.description || "");
+ formData.append("url_cover", collection.url_cover || "");
+ formData.append("roms", JSON.stringify(collection.roms));
+ if (collection.artwork) formData.append("artwork", collection.artwork);
+ return api.post(`/collections`, formData);
+}
+
+async function getCollections(): Promise<{ data: Collection[] }> {
+ return api.get("/collections");
+}
+
+async function getCollection(
+ id: number | undefined,
+): Promise<{ data: Collection }> {
+ return api.get(`/collections/${id}`);
+}
+
+async function updateCollection({
+ collection,
+ removeCover = false,
+}: {
+ collection: UpdatedCollection;
+ removeCover?: boolean;
+}): Promise<{ data: Collection }> {
+ const formData = new FormData();
+ formData.append("name", collection.name || "");
+ formData.append("description", collection.description || "");
+ formData.append("url_cover", collection.url_cover || "");
+ formData.append("roms", JSON.stringify(collection.roms));
+ if (collection.artwork) formData.append("artwork", collection.artwork);
+ return api.put(`/collections/${collection.id}`, formData, {
+ params: { remove_cover: removeCover },
+ });
+}
+
+async function deleteCollection({
+ collection,
+}: {
+ collection: Collection;
+}): Promise<{ data: MessageResponse }> {
+ return api.delete(`/collections/${collection.id}`);
+}
+
+export default {
+ createCollection,
+ getCollections,
+ getCollection,
+ updateCollection,
+ deleteCollection,
+};
diff --git a/frontend/src/services/api/rom.ts b/frontend/src/services/api/rom.ts
index 1bc6aedbd..fa6383ee4 100644
--- a/frontend/src/services/api/rom.ts
+++ b/frontend/src/services/api/rom.ts
@@ -1,13 +1,12 @@
import type {
AddRomsResponse,
MessageResponse,
- SearchCoverSchema,
SearchRomSchema,
} from "@/__generated__";
import api from "@/services/api/index";
import socket from "@/services/socket";
import storeDownload from "@/stores/download";
-import type { SimpleRom, DetailedRom } from "@/stores/roms";
+import type { DetailedRom, SimpleRom } from "@/stores/roms";
import { getDownloadLink } from "@/utils";
export const romApi = api;
@@ -32,11 +31,13 @@ async function uploadRoms({
async function getRoms({
platformId = null,
+ collectionId = null,
searchTerm = "",
orderBy = "name",
orderDir = "asc",
}: {
platformId?: number | null;
+ collectionId?: number | null;
searchTerm?: string | null;
orderBy?: string | null;
orderDir?: string | null;
@@ -44,6 +45,7 @@ async function getRoms({
return api.get(`/roms`, {
params: {
platform_id: platformId,
+ collection_id: collectionId,
search_term: searchTerm,
order_by: orderBy,
order_dir: orderDir,
@@ -91,14 +93,6 @@ async function searchRom({
});
}
-async function searchCover({
- searchTerm,
-}: {
- searchTerm: string;
-}): Promise<{ data: SearchCoverSchema[] }> {
- return api.get("/search/cover", { params: { search_term: searchTerm } });
-}
-
// Listen for multi-file download completion events
socket.on("download:complete", clearRomFromDownloads);
@@ -191,7 +185,6 @@ export default {
getRom,
downloadRom,
searchRom,
- searchCover,
updateRom,
deleteRoms,
updateUserRomProps,
diff --git a/frontend/src/services/api/sgdb.ts b/frontend/src/services/api/sgdb.ts
new file mode 100644
index 000000000..dc1eca314
--- /dev/null
+++ b/frontend/src/services/api/sgdb.ts
@@ -0,0 +1,16 @@
+import type { SearchCoverSchema } from "@/__generated__";
+import api from "@/services/api/index";
+
+export const romApi = api;
+
+async function searchCover({
+ searchTerm,
+}: {
+ searchTerm: string;
+}): Promise<{ data: SearchCoverSchema[] }> {
+ return api.get("/search/cover", { params: { search_term: searchTerm } });
+}
+
+export default {
+ searchCover,
+};
diff --git a/frontend/src/stores/collections.ts b/frontend/src/stores/collections.ts
new file mode 100644
index 000000000..0044b39b7
--- /dev/null
+++ b/frontend/src/stores/collections.ts
@@ -0,0 +1,54 @@
+import { defineStore } from "pinia";
+import type { CollectionSchema } from "@/__generated__";
+import { uniqBy } from "lodash";
+
+export type Collection = CollectionSchema;
+
+export default defineStore("collections", {
+ state: () => {
+ return {
+ allCollections: [] as Collection[],
+ searchText: "" as string,
+ };
+ },
+ getters: {
+ filteredCollections: ({ allCollections, searchText }) =>
+ allCollections.filter((p) =>
+ p.name.toLowerCase().includes(searchText.toLowerCase()),
+ ),
+ },
+ actions: {
+ _reorder() {
+ this.allCollections = this.allCollections.sort((a, b) => {
+ return a.name.localeCompare(b.name);
+ });
+ this.allCollections = uniqBy(this.allCollections, "id");
+ },
+ set(collections: Collection[]) {
+ this.allCollections = collections;
+ },
+ add(collection: Collection) {
+ this.allCollections.push(collection);
+ this._reorder();
+ },
+ update(collection: Collection) {
+ this.allCollections = this.allCollections.map((value) =>
+ value.id === collection.id ? collection : value,
+ );
+ this._reorder();
+ },
+ exists(collection: Collection) {
+ return (
+ this.allCollections.filter((p) => p.name == collection.name).length > 0
+ );
+ },
+ remove(collection: Collection) {
+ this.allCollections = this.allCollections.filter((p) => {
+ return p.name !== collection.name;
+ });
+ },
+ get(collectionId: number) {
+ return this.allCollections.find((p) => p.id === collectionId);
+ },
+ },
+});
diff --git a/frontend/src/stores/navigation.ts b/frontend/src/stores/navigation.ts
index 61c710c86..d2a4225f4 100644
--- a/frontend/src/stores/navigation.ts
+++ b/frontend/src/stores/navigation.ts
@@ -3,18 +3,37 @@ import { defineStore } from "pinia";
export default defineStore("navigation", {
state: () => ({
activePlatformsDrawer: false,
+ activeCollectionsDrawer: false,
activeSettingsDrawer: false,
}),
actions: {
switchActivePlatformsDrawer() {
+ this.activeCollectionsDrawer = false;
+ this.activeSettingsDrawer = false;
this.activePlatformsDrawer = !this.activePlatformsDrawer;
},
+ switchActiveCollectionsDrawer() {
+ this.activePlatformsDrawer = false;
+ this.activeSettingsDrawer = false;
+ this.activeCollectionsDrawer = !this.activeCollectionsDrawer;
+ },
switchActiveSettingsDrawer() {
+ this.activePlatformsDrawer = false;
+ this.activeCollectionsDrawer = false;
this.activeSettingsDrawer = !this.activeSettingsDrawer;
},
+ goHome() {
+ this.resetDrawers();
+ this.$router.push({ name: "dashboard" });
+ },
+ goScan() {
+ this.resetDrawers();
+ this.$router.push({ name: "scan" });
+ },
resetDrawers() {
this.activePlatformsDrawer = false;
+ this.activeCollectionsDrawer = false;
this.activeSettingsDrawer = false;
},
},
diff --git a/frontend/src/stores/platforms.ts b/frontend/src/stores/platforms.ts
index ef12e23ff..6df4aac3e 100644
--- a/frontend/src/stores/platforms.ts
+++ b/frontend/src/stores/platforms.ts
@@ -7,38 +7,45 @@ export type Platform = PlatformSchema;
export default defineStore("platforms", {
state: () => {
return {
- value: [] as Platform[],
+ all: [] as Platform[],
+ searchText: "" as string,
};
},
getters: {
- totalGames: ({ value }) =>
+ totalGames: ({ all: value }) =>
value.reduce((count, p) => count + p.rom_count, 0),
- filledPlatforms: ({ value }) => value.filter((p) => p.rom_count > 0),
+ filledPlatforms: ({ all }) => all.filter((p) => p.rom_count > 0),
+ filteredPlatforms: ({ all, searchText }) =>
+ all.filter(
+ (p) =>
+ p.rom_count > 0 &&
+ p.name.toLowerCase().includes(searchText.toLowerCase()),
+ ),
},
actions: {
_reorder() {
- this.value = this.value.sort((a, b) => {
+ this.all = this.all.sort((a, b) => {
return a.name.localeCompare(b.name);
});
- this.value = uniqBy(this.value, "id");
+ this.all = uniqBy(this.all, "id");
},
set(platforms: Platform[]) {
- this.value = platforms;
+ this.all = platforms;
},
add(platform: Platform) {
- this.value.push(platform);
+ this.all.push(platform);
this._reorder();
},
exists(platform: Platform) {
- return this.value.filter((p) => p.fs_slug == platform.fs_slug).length > 0;
+ return this.all.filter((p) => p.fs_slug == platform.fs_slug).length > 0;
},
remove(platform: Platform) {
- this.value = this.value.filter((p) => {
+ this.all = this.all.filter((p) => {
return p.slug !== platform.slug;
});
},
get(platformId: number) {
- return this.value.find((p) => p.id === platformId);
+ return this.all.find((p) => p.id === platformId);
},
},
});
diff --git a/frontend/src/stores/roms.ts b/frontend/src/stores/roms.ts
index 4906f62b5..e5f0b39ad 100644
--- a/frontend/src/stores/roms.ts
+++ b/frontend/src/stores/roms.ts
@@ -1,6 +1,7 @@
import type { SearchRomSchema } from "@/__generated__";
import type { DetailedRomSchema, RomSchema } from "@/__generated__/";
import { type Platform } from "@/stores/platforms";
+import { type Collection } from "@/stores/collections";
import type { ExtractPiniaStoreType } from "@/types";
import { groupBy, uniqBy } from "lodash";
import { nanoid } from "nanoid";
@@ -18,6 +19,8 @@ export type DetailedRom = DetailedRomSchema;
export default defineStore("roms", {
state: () => ({
currentPlatform: null as Platform | null,
+ currentCollection: null as Collection | null,
+ currentRom: null as DetailedRom | null,
allRoms: [] as SimpleRom[],
_grouped: [] as SimpleRom[],
_filteredIDs: [] as number[],
@@ -89,9 +92,15 @@ export default defineStore("roms", {
setCurrentPlatform(platform: Platform) {
this.currentPlatform = platform;
},
+ setCurrentRom(rom: DetailedRom) {
+ this.currentRom = rom;
+ },
setRecentRoms(roms: SimpleRom[]) {
this.recentRoms = roms;
},
+ setCurrentCollection(collection: Collection) {
+ this.currentCollection = collection;
+ },
set(roms: SimpleRom[]) {
this.allRoms = roms;
this._reorder();
@@ -104,6 +113,9 @@ export default defineStore("roms", {
this.allRoms = this.allRoms.map((value) =>
value.id === rom.id ? rom : value,
);
+ this.recentRoms = this.recentRoms.map((value) =>
+ value.id === rom.id ? rom : value,
+ );
this._reorder();
},
remove(roms: SimpleRom[]) {
diff --git a/frontend/src/stores/users.ts b/frontend/src/stores/users.ts
index e21793388..a5448b080 100644
--- a/frontend/src/stores/users.ts
+++ b/frontend/src/stores/users.ts
@@ -5,22 +5,22 @@ export type User = UserSchema;
export default defineStore("users", {
state: () => ({
- all: [] as User[],
+ allUsers: [] as User[],
}),
getters: {
- admins: (state) => state.all.filter((user) => user.role === "admin"),
+ admins: (state) => state.allUsers.filter((user) => user.role === "admin"),
},
actions: {
set(users: User[]) {
- this.all = users;
+ this.allUsers = users;
},
add(user: User) {
- this.all = this.all.concat(user);
+ this.allUsers = this.allUsers.concat(user);
},
update(user: User) {
- this.all = this.all.map((value) => {
+ this.allUsers = this.allUsers.map((value) => {
if (value.id === user.id) {
return user;
}
@@ -28,12 +28,12 @@ export default defineStore("users", {
});
},
remove(userId: number) {
- this.all = this.all.filter((value) => {
+ this.allUsers = this.allUsers.filter((value) => {
return value.id !== userId;
});
},
reset() {
- this.all = [];
+ this.allUsers = [];
},
},
});
diff --git a/frontend/src/types/emitter.d.ts b/frontend/src/types/emitter.d.ts
index f89124ffc..60e4322e9 100644
--- a/frontend/src/types/emitter.d.ts
+++ b/frontend/src/types/emitter.d.ts
@@ -1,4 +1,5 @@
import type { SaveSchema, StateSchema } from "@/__generated__";
+import type { Collection } from "@/stores/collections";
import type { Platform } from "@/stores/platforms";
import type { SimpleRom } from "@/stores/roms";
import type { User } from "@/stores/users";
@@ -18,8 +19,14 @@ export type SnackbarStatus = {
export type Events = {
showDeletePlatformDialog: Platform;
+ showCreateCollectionDialog: null;
+ showEditCollectionDialog: Collection;
+ showAddToCollectionDialog: SimpleRom[];
+ showRemoveFromCollectionDialog: SimpleRom[];
+ showDeleteCollectionDialog: Collection;
showMatchRomDialog: SimpleRom;
- showSearchCoverDialog: SimpleRom;
+ showSearchCoverDialog: string;
+ updateUrlCover: string;
showSearchRomDialog: null;
showEditRomDialog: SimpleRom;
showCopyDownloadLinkDialog: string;
diff --git a/frontend/src/views/Dashboard.vue b/frontend/src/views/Dashboard.vue
index bfb9f46f7..ad0814bac 100644
--- a/frontend/src/views/Dashboard.vue
+++ b/frontend/src/views/Dashboard.vue
@@ -1,11 +1,39 @@
-
-
-
+
+
+
+
diff --git a/frontend/src/views/Gallery/Collection.vue b/frontend/src/views/Gallery/Collection.vue
new file mode 100644
index 000000000..f817e4292
--- /dev/null
+++ b/frontend/src/views/Gallery/Collection.vue
@@ -0,0 +1,313 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/Gallery.vue b/frontend/src/views/Gallery/Platform.vue
similarity index 98%
rename from frontend/src/views/Gallery.vue
rename to frontend/src/views/Gallery/Platform.vue
index 4977a83d8..2351e9801 100644
--- a/frontend/src/views/Gallery.vue
+++ b/frontend/src/views/Gallery/Platform.vue
@@ -1,5 +1,5 @@
-
-
+
+
+
-
-
-
+
+
+
-
+
0 ||
- (rom.igdb_metadata?.dlcs ?? []).length > 0)
+ ((currentRom.igdb_metadata?.expansions ?? []).length > 0 ||
+ (currentRom.igdb_metadata?.dlcs ?? []).length > 0)
"
value="additionalcontent"
rounded="0"
@@ -157,9 +168,9 @@ watch(
-
-
+
+
+
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- mdi-controller
- mdi-magnify-scan
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
- mdi-controller
- mdi-magnify-scan
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
- {{ auth.user?.username }}
-
-
- {{ auth.user?.role }}
-
-
-
-
- UI Settings
- Library Management
-
- Administration
-
-
- Logout
-
-
-
-
-
- Logout
-
-
-
+
+
+
+
+
+
@@ -381,8 +111,7 @@ onMounted(async () => {
diff --git a/frontend/src/views/Play/Base.vue b/frontend/src/views/Play/Base.vue
index 2bcb1358d..ac27b39d3 100644
--- a/frontend/src/views/Play/Base.vue
+++ b/frontend/src/views/Play/Base.vue
@@ -81,7 +81,7 @@ onMounted(async () => {
:md="!gameRunning ? 8 : 4"
:xl="!gameRunning ? 6 : 2"
>
-
+
{
-
+
{{ rom.name }} {
})) ?? []
"
/>
-
-
|