AQ
This commit is contained in:
parent
aa88bb9802
commit
58c04ec3b9
@ -16,6 +16,11 @@ function hasCampaign(req, res, next){
|
||||
}).catch((err) => res.json({status: "error", err}));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasCampaign
|
||||
function hasUser(req, res, next){
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasCampaign,
|
||||
hasUser
|
||||
}
|
@ -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);
|
@ -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;
|
@ -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);
|
||||
|
@ -277,3 +277,19 @@ 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;
|
||||
}
|
3
client/src/locale/ca.json
Normal file
3
client/src/locale/ca.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"main-menu": "Menú Principal"
|
||||
}
|
@ -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"
|
||||
}
|
||||
}
|
@ -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"
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
@ -36,7 +36,7 @@ const defValues = {
|
||||
close: () => ClearWindow('edit_profile')
|
||||
},
|
||||
'settings': {
|
||||
id: 'ettings',
|
||||
id: 'settings',
|
||||
title: "Dragonroll settings",
|
||||
close: () => ClearWindow('settings')
|
||||
},
|
||||
|
@ -1,35 +1,39 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { AddContextMenu } from '../../services/ContextMenu';
|
||||
const props = defineProps(['options', 'selected']);
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { AddContextMenu, HideContextMenu } from '../../services/ContextMenu';
|
||||
const props = defineProps(['options', 'onselect', 'selected']);
|
||||
const options = props.options;
|
||||
const selected = props.selected;
|
||||
const selectCallback = props.onselect;
|
||||
const initialSelect = props.selected;
|
||||
const dropdown = ref(null);
|
||||
|
||||
const selected = ref(initialSelect);
|
||||
|
||||
onMounted(() => {
|
||||
let context = [];
|
||||
items.value.forEach(name => {
|
||||
watch(() => props.selected, () => {
|
||||
selected.value = props.selected;
|
||||
});
|
||||
options.forEach(name => {
|
||||
context.push({
|
||||
icon: selectedTags.value.includes(name) ? 'icons/iconoir/regular/check.svg' : false,
|
||||
icon: selected.value == name ? 'icons/iconoir/regular/check.svg' : false,
|
||||
name,
|
||||
action: () => {
|
||||
HideContextMenu();
|
||||
if(!selectedTags.value.includes(name)){
|
||||
SelectTab(name);
|
||||
} else { RemoveTag(name) }
|
||||
selected.value = name;
|
||||
selectCallback(name);
|
||||
}
|
||||
});
|
||||
});
|
||||
ShowContextMenu(context);
|
||||
|
||||
AddContextMenu(dropdown.value);
|
||||
AddContextMenu(dropdown.value, context, {dropdown: true});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="dropdown" ref="dropdown">
|
||||
<span>Hola</span>
|
||||
<span>{{ selected }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -78,9 +78,9 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<div class="main-user-actions">
|
||||
<button class="btn-primary button-small sound-click" v-on:click.prevent="EditProfile">Edit profile</button>
|
||||
<button class="btn-primary button-small sound-click" v-on:click.prevent="EditSettings">Settings</button>
|
||||
<button class="btn-primary button-small sound-click" v-on:click.prevent="LogOut">Log out</button>
|
||||
<button class="btn-primary button-small sound-click" v-on:click.prevent="EditProfile">{{ $t("main-menu.edit-profile") }}</button>
|
||||
<button class="btn-primary button-small sound-click" v-on:click.prevent="EditSettings">{{ $t("main-menu.settings") }}</button>
|
||||
<button class="btn-primary button-small sound-click" v-on:click.prevent="LogOut">{{ $t("main-menu.log-out") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -82,13 +82,13 @@ function OpenBookAnvil(){
|
||||
|
||||
<EditUserPartial></EditUserPartial>
|
||||
|
||||
<h1>{{ $t("main-menu")}}</h1>
|
||||
<h1>{{ $t("main-menu.main-menu")}}</h1>
|
||||
|
||||
<div class="button-container">
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenCampaigns" ref="campaignButton">Campaigns</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenCampaigns" ref="campaignButton">{{ $t("main-menu.campaigns") }}</button>
|
||||
<hr>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenCompendium">The Cosmic Compendium</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenBookAnvil">Book Anvil</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenCompendium">{{ $t("main-menu.cosmic-compendium") }}</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenBookAnvil">{{ $t("main-menu.book-anvil") }}</button>
|
||||
</div>
|
||||
<VersionRender></VersionRender>
|
||||
</div>
|
||||
|
@ -5,8 +5,8 @@ import { GetUser } from '@/services/User'
|
||||
|
||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||
import Tabs from '../partials/Tabs.vue';
|
||||
import { I18nD, I18nN } from 'vue-i18n';
|
||||
import Dropdown from '../partials/Dropdown.vue';
|
||||
import { GetUserSetting, SetUserSetting } from '../../services/User';
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
@ -17,20 +17,36 @@ let id = data.id;
|
||||
|
||||
let rows = ref(["Account settings"]);
|
||||
|
||||
const languageOptions = ref(["English", "Spanish", "Catalan"])
|
||||
const langSelector = ref(null);
|
||||
const currentLanguage = ref("");
|
||||
|
||||
onBeforeMount(() => {
|
||||
let codes = {
|
||||
"en": "English",
|
||||
"es": "Spanish",
|
||||
"ca": "Catalan"
|
||||
}
|
||||
GetUserSetting('lang').then(value => {
|
||||
currentLanguage.value = codes[value ?? 'en']
|
||||
console.log(currentLanguage.value)
|
||||
});
|
||||
if(GetUser().admin) rows.value.push("Site Administration");
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {width: 500, height: 380});
|
||||
SetSize(id, {width: 400, height: 480});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
|
||||
function OnLanguageChange(){
|
||||
I18n.locale = langSelector.value.value;
|
||||
async function OnLanguageChange(value){
|
||||
let codes = {
|
||||
"English": "en",
|
||||
"Spanish": "es",
|
||||
"Catalan": "ca"
|
||||
}
|
||||
await SetUserSetting("lang", codes[value]);
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -42,8 +58,13 @@ function OnLanguageChange(){
|
||||
<!-- Body -->
|
||||
<Tabs :rows="rows">
|
||||
<template #account-settings>
|
||||
Language: <Dropdown :options="languageOptions" :select="OnLanguageChange"></Dropdown>
|
||||
</template>
|
||||
<div class="form-container">
|
||||
<div class="form-element">
|
||||
<label>Language: </label>
|
||||
<Dropdown :options="languageOptions" :onselect="OnLanguageChange" :selected="currentLanguage"></Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>Hola
|
||||
<template #site-administration>
|
||||
|
||||
</template>
|
||||
@ -54,9 +75,6 @@ function OnLanguageChange(){
|
||||
|
||||
<style scoped>
|
||||
.window-wrapper {
|
||||
min-width: 700px;
|
||||
min-height: 630px;
|
||||
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -108,12 +108,12 @@ function InitValues(){
|
||||
rarity.value.addEventListener("click", () => {
|
||||
ShowContextMenu(rarities)
|
||||
});
|
||||
AddContextMenu(rarity.value, rarities)
|
||||
AddContextMenu(rarity.value, rarities, {dropdown: true})
|
||||
|
||||
weaponType.value.addEventListener("click", () => {
|
||||
ShowContextMenu(weapon_types)
|
||||
});
|
||||
AddContextMenu(weaponType.value, weapon_types);
|
||||
AddContextMenu(weaponType.value, weapon_types, {dropdown: true});
|
||||
|
||||
item_name.value.addEventListener('blur', () => {
|
||||
concept.value.name = item_name.value.textContent;
|
||||
|
Loading…
Reference in New Issue
Block a user