diff --git a/backend/src/controllers/mods.js b/backend/src/controllers/mods.js
index 9d2de1d..0d49fd2 100644
--- a/backend/src/controllers/mods.js
+++ b/backend/src/controllers/mods.js
@@ -2,6 +2,9 @@ const handleError = require("../middleware/errors");
const mod_service = require("../services/modService");
const { authorizeModModification, authenticateToken } = require("../middleware/auth");
+
+// Mods
+
async function listMods(req, res) {
try {
// Query
@@ -65,5 +68,63 @@ async function deleteMod(req, res) {
}
+// Versions
-module.exports = { listMods, getModByName, createMod, modifyMod, deleteMod };
\ No newline at end of file
+async function createModVersion(req, res) {
+ try {
+ // Authorize
+ await authorizeModModification(req);
+ // Query
+ const name = req.params.name
+ const version_data = req.body;
+ const query_result = await mod_service.createModVersion(name, version_data);
+ res.json(query_result);
+ } catch (error) {
+ handleError(error, res);
+ }
+}
+
+async function modifyModVersion(req, res) {
+ try {
+ // Authorize
+ await authorizeModModification(req);
+ // Query
+ const name = req.params.name
+ const version_data = req.body;
+ const query_result = await mod_service.modifyModVersion(name, version_data);
+ res.json(query_result);
+ } catch (error) {
+ handleError(error, res);
+ }
+}
+
+async function getModVersions(req, res) {
+ try {
+ // Query
+ const name = req.params.name
+ const filters = req.query;
+ const query_result = await mod_service.getModVersions(name, filters);
+ res.json(query_result);
+ } catch (error) {
+ handleError(error, res);
+ }
+}
+
+async function deleteModVersion(req, res) {
+ try {
+ // Authorize
+ await authorizeModModification(req);
+ // Query
+ const name = req.params.name
+ const version_infos = req.body;
+ const query_result = await mod_service.deleteModVersion(name, version_infos);
+ res.json(query_result);
+ } catch (error) {
+ handleError(error, res);
+ }
+}
+
+
+
+module.exports = { listMods, getModByName, createMod, modifyMod, deleteMod,
+ createModVersion, modifyModVersion, getModVersions, deleteModVersion };
\ No newline at end of file
diff --git a/backend/src/models/mod.js b/backend/src/models/mod.js
index 598b265..c2a5b90 100644
--- a/backend/src/models/mod.js
+++ b/backend/src/models/mod.js
@@ -6,7 +6,6 @@ const db = getDatabase();
// --- Get ---
async function listMods(filters) {
- console.debug(filters);
return await db.query(`SELECT name, display_name, author, description FROM Mods
WHERE
(CASE WHEN @search IS NOT NULL THEN
@@ -34,29 +33,44 @@ async function getFullModInfos(name) {
return [await base_infos, await other_infos, await tags];
}
-async function listVersions(mod_name) {
- return await db.query("SELECT * FROM ModVersions WHERE mod = ?", [mod_name]);
-}
-
async function listTags(mod_name) {
return await db.query(`SELECT tag FROM ModTags WHERE mod = ?`, [mod_name]);
}
-async function getVersionByNumber(mod_name, version_number) {
- return await db.query(`SELECT * FROM ModVersions
- WHERE mod = ?
- AND version_number = ?;`,
- [mod_name, version_number]);
+//TODO rm
+async function listAllModVersions() {
+ return await db.query(`SELECT * FROM ModVersions`);
}
-async function getVersion(mod_name, version_number, game_version, platform, environment) {
- return await db.query(`SELECT * FROM ModVersions
- WHERE mod = ?
- AND version_number = ?
- AND game_version = ?
- AND platform = ?
- AND environment = ?;`,
- [mod_name, version_number, game_version, platform, environment]);
+async function getModVersions(mod_name, filters) {
+ return await db.query(`SELECT * FROM ModVersions
+ WHERE mod = @mod_name
+ AND
+ (CASE WHEN @version_number IS NOT NULL THEN
+ version_number = @version_number ELSE TRUE END)
+ AND
+ (CASE WHEN @channel IS NOT NULL THEN
+ channel = @channel ELSE TRUE END)
+ AND
+ (CASE WHEN @game_version IS NOT NULL THEN
+ game_version = @game_version ELSE TRUE END)
+ AND
+ (CASE WHEN @platform IS NOT NULL THEN
+ platform = @platform ELSE TRUE END)
+ AND
+ (CASE WHEN @environment IS NOT NULL THEN
+ environment = @environment ELSE TRUE END)
+ ;`, {mod_name, ...filters});
+}
+
+async function getStrictModVersion(mod_name, version_number, game_version, platform, environment) {
+ return await db.query(`SELECT * FROM ModVersions
+ WHERE mod = ?
+ AND version_number = ?
+ AND game_version = ?
+ AND platform = ?
+ AND environment = ?
+ ;`, [mod_name, version_number, game_version, platform, environment]);
}
// --- Create ---
@@ -97,11 +111,15 @@ async function createMod(name, display_name, author, description, mod_infos) {
return;
}
-async function addVersion(mod, version_number, channel, changelog, release_date, game_version, platform, environment, url) {
+async function createModVersion(mod, version_infos) {
+ const { version_number, channel, changelog, release_date, game_version, platform, environment, url } = version_infos;
+
await db.run(`INSERT INTO ModVersions (mod, version_number, channel, changelog, release_date, game_version, environment, platform, url)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);`,
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);`,
[mod, version_number, channel, changelog, release_date, game_version, environment, platform, url]);
+
+
return;
}
@@ -143,7 +161,7 @@ async function deleteMod(name) {
return;
}
-async function deleteVersion(name, version_number, game_version, platform, environment) {
+async function deleteModVersion(name, version_number, game_version, platform, environment) {
await db.run(`DELETE FROM ModVersions WHERE mod = ?
AND version_number = ?
AND game_version = ?
@@ -195,8 +213,8 @@ async function containsTag(name, tag) {
// --- Exports ---
module.exports = { listMods, getModByName, getFullModInfos,
- listVersions, listTags, getVersionByNumber, getVersion,
- createMod, addVersion, addTags,
+ getModVersions, listTags, getStrictModVersion,
+ createMod, createModVersion, addTags,
updateMod,
- deleteMod, deleteVersion, deleteTags,
- exists };
\ No newline at end of file
+ deleteMod, deleteModVersion, deleteTags,
+ exists, listAllModVersions };
\ No newline at end of file
diff --git a/backend/src/routes/mods.js b/backend/src/routes/mods.js
index 82c1e02..aec98a3 100644
--- a/backend/src/routes/mods.js
+++ b/backend/src/routes/mods.js
@@ -24,4 +24,26 @@ router.delete("/:name", async (req,res) => {
});
+
+// Create a mod version
+router.post("/:name/versions", async (req, res) => {
+ controller.createModVersion(req, res);
+});
+
+// Modify a mod version
+router.put("/:name/versions", async (req,res) => {
+ controller.modifyModVersion(req,res);
+});
+
+// Get mod versions
+router.get("/:name/versions", async (req,res) => {
+ controller.getModVersions(req, res);
+});
+
+// Delete mod version
+router.delete("/:name/versions", async (req,res) => {
+ controller.deleteModVersion(req, res);
+});
+
+
module.exports = router;
\ No newline at end of file
diff --git a/backend/src/services/modService.js b/backend/src/services/modService.js
index e26fdc4..f1bf981 100644
--- a/backend/src/services/modService.js
+++ b/backend/src/services/modService.js
@@ -5,7 +5,8 @@ const { mdToHtml } = require("../utils/convert");
const { sanitizeModData } = require("../utils/sanitize");
-// --- Get ---
+// --- Mods ---
+
async function listMods(filters) {
//TODO Validate filters
@@ -17,6 +18,7 @@ async function listMods(filters) {
return await model.listMods({...filters});
}
+
async function getModByName(name) {
const res = await model.getModByName(name);
if (res.length == 0) {
@@ -25,6 +27,7 @@ async function getModByName(name) {
return res[0];
}
+
async function getFullModInfos(name) {
const [base_infos, other_infos, tags] = await model.getFullModInfos(name);
// Check
@@ -37,17 +40,6 @@ async function getFullModInfos(name) {
return res;
}
-async function getModVersion(infos) {
- const { mod, version_number, game_version, platform, environment} = infos;
- const res = await model.getModVersion(mod, version_number, game_version, platform, environment);
- if (res.length == 0) {
- throw new AppError(404, "Cannot find mod with this name", "Not found");
- }
- return res[0];
-}
-
-
-// --- Create ---
async function createMod(mod_data, author) {
@@ -67,46 +59,9 @@ async function createMod(mod_data, author) {
await model.createMod(name, display_name, author, description, mod_infos);
// Return
- return getModByName(name);
+ return await getModByName(name);
}
-async function addVersion(version_data) {
-
- // Validate
- //TODO
- console.warn("Skipping validity checks for addVersion");
-
- // Generate data
- const { mod_name, version_number, channel, changelog, game_version,
- platform, environment, url } = version_data; // Split
- changelog = await mdToHtml(changelog); // Convert
- await sanitizeModData(mod_data); // Sanitize
- const release_date = (new Date()).toLocaleDateString();
-
- // Write changes
- await model.addVersion(mod_name, version_number, channel, changelog,
- release_date, game_version, platform, environment, url); // Database
-
- // Return
- return await model.getModVersion(mod_name, version_number, game_version, platform, environment );
-}
-
-async function addTags(mod, tags) {
-
- // Validate
- //TODO
- console.warn("Skipping validity checks for addTags");
-
- // Write changes
- await model.addTags(mod, tags);
-
- // Return
- const { tags:res } = await model.getFullModInfos(mod);
- return { "mod": mod, "tags": res};
-
-}
-
-// --- Update ---
async function updateMod(diff_data) {
//TODO
@@ -114,9 +69,6 @@ async function updateMod(diff_data) {
}
-
-// Delete
-
async function deleteMod(name) {
// Check existence
@@ -138,22 +90,102 @@ async function deleteMod(name) {
return mod;
}
-async function deleteVersion(version_infos) {
+
+
+// --- Versions ---
+
+
+async function createModVersion(mod_name, version_data) {
+
+ // Validate
+ //TODO
+ console.warn("Skipping validity checks for createModVersion");
+
+ // Generate data
+ const { version_number, channel, changelog, game_version,
+ platform, environment, url } = version_data; // Split
+
+ // changelog = await mdToHtml(changelog); // Convert
+ // await sanitizeModData(mod_data); // Sanitize
+ const release_date = Date.now();
+
+ // Write changes
+ await model.createModVersion(mod_name, {version_number, channel, changelog,
+ release_date, game_version, platform, environment, url}); // Database
+
+ // Return
+ return await model.getStrictModVersion(mod_name, version_number, game_version, platform, environment );
+}
+
+
+async function modifyModVersion(infos) {
+ throw new AppError(501, "Not implemented");
+}
+
+
+async function getModVersions(mod_name, filters) {
+
+ // Validation
+ //TODO
+ console.warn("Skipping getModVersions validation (Not implemented)");
+
+ filters.version_number = filters.version_number || null;
+ filters.channel = filters.channel || null;
+ filters.game_version = filters.game_version || null;
+ filters.platform = filters.platform || null;
+ filters.environment = filters.environment || null;
+
+ // Query
+ const res= await model.getModVersions(mod_name, {...filters});
+ return res;
+}
+
+// async function getModVersion(version_infos) {
+// const { mod, version_number, game_version, platform, environment} = version_infos;
+// const res = await model.getModVersion(mod, version_number, game_version, platform, environment);
+// if (res.length == 0) {
+// throw new AppError(404, "Cannot find mod with this name", "Not found");
+// }
+// return res[0];
+// }
+
+
+async function deleteModVersion(mod_name, version_infos) {
// Validate
// TODO
// Generate data
- const res = await getModVersion(version_infos);
- const { mod, version_number, game_version, platform, environment} = version_infos;
+ const { version_number, game_version, platform, environment } = version_infos;
+ const res = await model.getStrictModVersion(mod_name, version_number, game_version, platform, environment );
// Write changes to db
- await model.deleteVersion(mod, version_number, game_version, platform, environment);
+ await model.deleteModVersion(mod_name, version_number, game_version, platform, environment);
// Return
return res;
}
+
+// --- Tags ---
+
+
+async function addTags(mod, tags) {
+
+ // Validate
+ //TODO
+ console.warn("Skipping validity checks for addTags");
+
+ // Write changes
+ await model.addTags(mod, tags);
+
+ // Return
+ const { tags:res } = await model.getFullModInfos(mod);
+ return { "mod": mod, "tags": res};
+
+}
+
+
async function deleteTags(mod, tags) {
// Validate (check existence)
@@ -168,7 +200,10 @@ async function deleteTags(mod, tags) {
return { "mod": mod, "tags": res};
}
+
+
+
module.exports = { listMods, getModByName, getFullModInfos,
- createMod, addTags, addVersion,
- updateMod,
- deleteMod, deleteTags, deleteVersion };
\ No newline at end of file
+ createMod, updateMod, deleteMod,
+ createModVersion, modifyModVersion, getModVersions, deleteModVersion,
+ addTags, deleteTags };
\ No newline at end of file
diff --git a/frontend/src/components/Cards/small_card.jsx b/frontend/src/components/Cards/small_card.jsx
new file mode 100644
index 0000000..539c9f2
--- /dev/null
+++ b/frontend/src/components/Cards/small_card.jsx
@@ -0,0 +1,34 @@
+// Preact
+import { h } from 'preact' // Necessary ?
+
+// Styles
+import styles from './small_card.module.css'
+
+// Images
+import Thumbnail from '../../assets/mod.svg'
+import Banner from '../../assets/example.jpg'
+
+function SmallCard({item, variant, href}) {
+ console.debug(variant, item);
+
+ if (variant === 'empty') {
+ return (
+
+ {item}
- You have no favorites for the moment -
-
-
-