diff --git a/backend/config/middleware.js b/backend/config/middleware.js
index 6af9f00a..2e389ed9 100644
--- a/backend/config/middleware.js
+++ b/backend/config/middleware.js
@@ -16,6 +16,11 @@ function hasCampaign(req, res, next){
}).catch((err) => res.json({status: "error", err}));
}
+function hasUser(req, res, next){
+
+}
+
module.exports = {
- hasCampaign
+ hasCampaign,
+ hasUser
}
\ No newline at end of file
diff --git a/backend/models/User.js b/backend/models/User.js
index 232b9722..abac13be 100755
--- a/backend/models/User.js
+++ b/backend/models/User.js
@@ -8,7 +8,8 @@ const UserSchema = new Schema({
password: { type: String, required: true },
date: { type: Date, default: Date.now},
admin: {type: Boolean, default: false},
- image: { type: String }
+ image: { type: String },
+ settings: { type: Object }
});
module.exports = mongoose.model('User', UserSchema);
\ No newline at end of file
diff --git a/backend/routes/user.js b/backend/routes/user.js
index 6de0cb35..ab02d20a 100755
--- a/backend/routes/user.js
+++ b/backend/routes/user.js
@@ -8,6 +8,8 @@ const secret = require('../config/keys').secret;
const rateLimitMiddleware = require("../config/rate-limiter");
const { default: jwtDecode } = require('jwt-decode');
+const { hasUser } = require('../config/middleware');
+
const User = require("../models/User");
const upload = require("../config/storage");
@@ -96,6 +98,7 @@ router.post('/login', rateLimitMiddleware, (req, res) => {
name: user.name,
email: user.email,
admin: user.admin,
+ settings: user.settings
}
jwt.sign(payload, secret, {
expiresIn: 172800
@@ -151,4 +154,24 @@ router.get("/has-admin", (req, res) => {
});
});
+router.post("/update-settings", passport.authenticate('jwt', {session: false}), (req, res) => {
+ User.updateOne(req.user, {settings: req.body.settings}).then(() => {
+ res.json({
+ status: "ok",
+ settings: req.body.settings
+ })
+ }).catch((err) => {
+ res.json({status: "error", msg: "internal"})
+ });
+});
+
+router.get('/get-settings', passport.authenticate('jwt', {session: false}), (req, res) => {
+ User.findOne(req.user).then((data) => {
+ res.json({
+ status: "ok",
+ settings: data.settings
+ });
+ }).catch((err) => res.json({status: "error", msg: "internal"}));
+})
+
module.exports = router;
\ No newline at end of file
diff --git a/client/src/App.vue b/client/src/App.vue
index 2733ba0b..27f62da4 100644
--- a/client/src/App.vue
+++ b/client/src/App.vue
@@ -14,8 +14,6 @@ import { ImportModule, GetModulesToLoad } from './services/Modules'
import { CreateWindow } from './services/Windows';
import { FetchVanillaResources } from './services/Resources';
-console.clear();
-console.log("%cLoaded!!!", "color: #22ff22; font-size: 24px");
LoadUser();
SetEmitter(emitter);
diff --git a/client/src/assets/main.css b/client/src/assets/main.css
index 69e9710a..1d744c5a 100644
--- a/client/src/assets/main.css
+++ b/client/src/assets/main.css
@@ -276,4 +276,20 @@ span.legendary {
}
span.artifact {
color: var(--color-artifact);
+}
+
+.form-container {
+ width: 100%;
+}
+
+.form-element {
+ padding: 10px 0 10px 0;
+ margin: 0 10px 0 10px;
+ display: flex;
+ align-items: center;
+ border-bottom: 1px dashed var(--color-border);
+}
+
+.form-element label {
+ flex-grow: 1;
}
\ No newline at end of file
diff --git a/client/src/locale/ca.json b/client/src/locale/ca.json
new file mode 100644
index 00000000..8074d47d
--- /dev/null
+++ b/client/src/locale/ca.json
@@ -0,0 +1,3 @@
+{
+ "main-menu": "Menú Principal"
+}
\ No newline at end of file
diff --git a/client/src/locale/en.json b/client/src/locale/en.json
index 19f5a5f2..b108643a 100644
--- a/client/src/locale/en.json
+++ b/client/src/locale/en.json
@@ -1,3 +1,11 @@
{
- "main-menu": "Main Menu"
+ "main-menu": {
+ "main-menu": "Main Menu",
+ "campaigns": "Campaigns",
+ "cosmic-compendium": "The Cosmic Compendium",
+ "book-anvil": "Book Anvil",
+ "edit-profile": "Edit Profile",
+ "settings": "Settings",
+ "log-out": "Log Out"
+ }
}
\ No newline at end of file
diff --git a/client/src/locale/es.json b/client/src/locale/es.json
index 8074d47d..3cae136b 100644
--- a/client/src/locale/es.json
+++ b/client/src/locale/es.json
@@ -1,3 +1,11 @@
{
- "main-menu": "Menú Principal"
+ "main-menu": {
+ "main-menu": "Menú Principal",
+ "campaigns": "Campañas",
+ "cosmic-compendium": "La Libreria Cósmica",
+ "book-anvil": "Forjador de Libros",
+ "edit-profile": "Editar Perfil",
+ "settings": "Ajustes",
+ "log-out": "Cerrar sesión"
+ }
}
\ No newline at end of file
diff --git a/client/src/main.js b/client/src/main.js
index 781bb3f6..11295efc 100644
--- a/client/src/main.js
+++ b/client/src/main.js
@@ -8,8 +8,10 @@ import router from './router'
import EN from './locale/en.json'
import ES from './locale/es.json'
+import CA from './locale/ca.json'
import mitt from 'mitt';
+import { GetUser, GetUserSetting } from './services/User'
const emitter = mitt();
const app = createApp(App);
@@ -22,12 +24,23 @@ app.config.globalProperties.rollWindows = {
edit_profile: reactive([]),
};
+
+console.clear();
+console.log("%cLoaded!!!", "color: #22ff22; font-size: 24px");
+
+// Determinem el locale
+let locale = 'en';
+if(GetUser()) locale = await GetUserSetting('lang');
+console.log(locale);
+
const i18n = createI18n({
legacy: false,
- locale: 'en',
+ locale,
+ fallbackLocale: 'en',
messages: {
en: EN,
es: ES,
+ ca: CA
}
});
diff --git a/client/src/services/ContextMenu.js b/client/src/services/ContextMenu.js
index 9e8785b7..c2ca283f 100644
--- a/client/src/services/ContextMenu.js
+++ b/client/src/services/ContextMenu.js
@@ -77,13 +77,24 @@ function PopulateContextMenu(val){
children.forEach((el) => contextMenu.appendChild(el));
}
-function AddContextMenu(element, val){
+function AddContextMenu(element, val, options = {}){
element._dr_context = val;
- element.addEventListener('contextmenu', (e) => {
+
+ function show(e){
e.preventDefault();
PopulateContextMenu(val);
Show();
- });
+ if(options.dropdown){
+ let rect = element.getBoundingClientRect();
+ let contextMenu = document.getElementById('context-menu');
+ contextMenu.style.top = rect.bottom + "px";
+ contextMenu.style.left = rect.left + "px";
+ console.log(rect.top);
+ }
+ }
+
+ element.addEventListener('contextmenu', show);
+ if(options.dropdown) element.addEventListener('click', show);
}
diff --git a/client/src/services/User.js b/client/src/services/User.js
index 12a6d60c..301550f8 100644
--- a/client/src/services/User.js
+++ b/client/src/services/User.js
@@ -24,6 +24,25 @@ async function HasAdmin(){
return response.data.status != "init";
}
+function SetUserSetting(key, value){
+ return new Promise((resolve, reject) => {
+ let user = GetUser()
+ if(!user.settings) user.settings = {};
+ user.settings[key] = value;
+ Api().post('/user/update-settings', {settings: user.settings}).then(response => {
+ resolve(response.data.settings);
+ });
+ });
+}
+
+function GetUserSetting(key){
+ return new Promise((resolve, reject) => {
+ Api().get('/user/get-settings').then(response => {
+ resolve(response.data.settings[key]);
+ });
+ });
+}
+
function GetUser(){
const token = localStorage.getItem('token');
@@ -66,5 +85,7 @@ export {
LoadUser,
IsAdmin,
LogoutUser,
- HasAdmin
+ HasAdmin,
+ GetUserSetting,
+ SetUserSetting
}
\ No newline at end of file
diff --git a/client/src/services/Windows.js b/client/src/services/Windows.js
index 8a68dd1b..1a9758ae 100644
--- a/client/src/services/Windows.js
+++ b/client/src/services/Windows.js
@@ -36,7 +36,7 @@ const defValues = {
close: () => ClearWindow('edit_profile')
},
'settings': {
- id: 'ettings',
+ id: 'settings',
title: "Dragonroll settings",
close: () => ClearWindow('settings')
},
diff --git a/client/src/views/partials/Dropdown.vue b/client/src/views/partials/Dropdown.vue
index 0ba40a1c..c9eb037c 100644
--- a/client/src/views/partials/Dropdown.vue
+++ b/client/src/views/partials/Dropdown.vue
@@ -1,35 +1,39 @@