More thinngeijidjioashdisa
This commit is contained in:
parent
34a8e1d120
commit
1991fd8f02
@ -10,7 +10,7 @@
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous">
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js" integrity="sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8" crossorigin="anonymous"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script>
|
||||
<title>Aran blog</title>
|
||||
<title>Dragonroll</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
BIN
client/public/sounds/click.wav
Normal file
BIN
client/public/sounds/click.wav
Normal file
Binary file not shown.
BIN
client/public/sounds/close.wav
Normal file
BIN
client/public/sounds/close.wav
Normal file
Binary file not shown.
BIN
client/public/sounds/roll1.wav
Normal file
BIN
client/public/sounds/roll1.wav
Normal file
Binary file not shown.
BIN
client/public/sounds/roll2.wav
Normal file
BIN
client/public/sounds/roll2.wav
Normal file
Binary file not shown.
BIN
client/public/sounds/snap.wav
Normal file
BIN
client/public/sounds/snap.wav
Normal file
Binary file not shown.
@ -45,6 +45,21 @@ a {
|
||||
margin: 4.25px;
|
||||
}
|
||||
|
||||
.buttons-row {
|
||||
width: 100%;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 1px;
|
||||
@ -89,7 +104,8 @@ input[type=text]:focus, input[type=password]:focus, input[type=email]:focus {
|
||||
button {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
padding: 18px;
|
||||
|
||||
padding: 14px;
|
||||
font-size: 15px;
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
|
12
client/src/services/Dragonroll.js
Normal file
12
client/src/services/Dragonroll.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { ClearAll, ClearWindow, CreateWindow } from './Windows';
|
||||
|
||||
function DisplayCampaign(data){
|
||||
ClearAll();
|
||||
CreateWindow('campaign_preview', {
|
||||
title: data.name
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
DisplayCampaign
|
||||
};
|
@ -7,9 +7,66 @@ const windows = {
|
||||
main_menu: ref([]),
|
||||
edit_profile: ref([]),
|
||||
account_settings: ref([]),
|
||||
db_window: ref([])
|
||||
db_window: ref([]),
|
||||
campaign_list: ref([]),
|
||||
new_campaign: ref([]),
|
||||
join_campaign: ref([]),
|
||||
campaign_preview: ref([])
|
||||
};
|
||||
|
||||
const defValues = {
|
||||
'login': {
|
||||
id: 'login',
|
||||
title: 'Login'
|
||||
},
|
||||
'register': {
|
||||
id: 'register',
|
||||
title: 'Register'
|
||||
},
|
||||
'main_menu': {
|
||||
id: 'main_menu',
|
||||
title: "DragonRoll"
|
||||
},
|
||||
'edit_profile': {
|
||||
id: 'edit_profile',
|
||||
title: "Edit Profile",
|
||||
close: true
|
||||
},
|
||||
'account_settings': {
|
||||
id: 'account_settings',
|
||||
title: "Dragonroll settings",
|
||||
close: true
|
||||
},
|
||||
'campaign_list': {
|
||||
id: 'campaign_list',
|
||||
title: 'Campaigns',
|
||||
back: () => {
|
||||
ClearWindow('campaign_list');
|
||||
CreateWindow('main_menu');
|
||||
}
|
||||
},
|
||||
'new_campaign': {
|
||||
id: 'new_campaign',
|
||||
title: 'Create campaign',
|
||||
parent: 'campaign_list',
|
||||
close: true
|
||||
},
|
||||
'join_campaign': {
|
||||
id: 'join_campaign',
|
||||
title: 'Join campaign',
|
||||
parent: 'campaign_list',
|
||||
close: true
|
||||
},
|
||||
'campaign_preview': {
|
||||
id: 'campaign_preview',
|
||||
title: "Campaign Preview",
|
||||
back: () => {
|
||||
ClearWindow('campaign_preview');
|
||||
CreateWindow('campaign_list')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const reload = ref(0);
|
||||
|
||||
let ReloadRef = () => { return reload };
|
||||
@ -107,35 +164,57 @@ function ResetPosition(id, pos){
|
||||
}
|
||||
|
||||
|
||||
function CreateWindow(data){
|
||||
if(windows[data.type] === undefined){
|
||||
console.error("Window type " + data.type + " is not defined!");
|
||||
function CreateWindow(type, data = {}){
|
||||
let finalData = {...{type}, ...defValues[type], ...data}
|
||||
|
||||
console.log(finalData);
|
||||
|
||||
if(windows[finalData.type] === undefined){
|
||||
console.error("Window type " + finalData.type + " is not defined!");
|
||||
return;
|
||||
}
|
||||
|
||||
let contains = false;
|
||||
for (let i = 0; i < windows[data.type].length; i++) {
|
||||
if(windows[data.type][i].id == data.id){
|
||||
for (let i = 0; i < windows[finalData.type].value.length; i++) {
|
||||
if(windows[finalData.type].value[i].id == finalData.id){
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!contains) {
|
||||
windows[data.type].value.push(data);
|
||||
windows[finalData.type].value.push(finalData);
|
||||
// reload.value += 1;
|
||||
|
||||
setTimeout(() => SetOnTop(data.id), 0);
|
||||
setTimeout(() => SetOnTop(finalData.id), 0);
|
||||
}
|
||||
}
|
||||
|
||||
function CreateChildWindow(parentId, type, data = {}){
|
||||
let finalData = {...{type}, ...defValues[type], ...data}
|
||||
|
||||
let parent = GetWindowWithId(parentId);
|
||||
if(parent.children) parent.children.push(finalData.id);
|
||||
else parent.children = [finalData.id];
|
||||
CreateWindow(type, data);
|
||||
}
|
||||
|
||||
function ClearAll(){
|
||||
Object.keys(windows).forEach((key) => {
|
||||
windows[key].value = [];
|
||||
});
|
||||
}
|
||||
|
||||
function ClearWindows(data){
|
||||
windows[data.type].value = [];
|
||||
for (let i = 0; i < windows[data.type].value.length; i++) {
|
||||
ClearWindow(windows[data.type].value[i].id);
|
||||
}
|
||||
// reload.value += 1;
|
||||
}
|
||||
|
||||
function ClearWindow(id){
|
||||
let win = GetWindowWithId(id);
|
||||
if(!win) return;
|
||||
if(win.children) for(let i = 0; i < win.children.length; i++) ClearWindow(win.children[i]);
|
||||
windows[win.type].value = windows[win.type].value.filter((e) => {return e.id !== id});
|
||||
// reload.value += 1;
|
||||
}
|
||||
@ -174,7 +253,9 @@ export {
|
||||
ReloadRef,
|
||||
ClearWindows,
|
||||
CreateWindow,
|
||||
CreateChildWindow,
|
||||
GetWindowWithId,
|
||||
SaveWindowPos,
|
||||
ClearWindow
|
||||
ClearWindow,
|
||||
ClearAll
|
||||
}
|
@ -9,18 +9,10 @@ import { CreateWindow } from '@/services/Windows'
|
||||
|
||||
onMounted(() => {
|
||||
if(GetUser()){
|
||||
CreateWindow({
|
||||
type: "main_menu",
|
||||
id: "main_menu",
|
||||
title: "Dragonroll"
|
||||
})
|
||||
CreateWindow('main_menu')
|
||||
return;
|
||||
}
|
||||
CreateWindow({
|
||||
type: "login",
|
||||
id: "login",
|
||||
title: "Login"
|
||||
});
|
||||
CreateWindow('login');
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
<script setup>
|
||||
import ErrorMessage from '@/components/partials/ErrorMessage.vue'
|
||||
|
||||
import { ref } from 'vue';
|
||||
import Api from '@/services/Api.js'
|
||||
import { useRouter, RouterLink } from 'vue-router'
|
||||
|
||||
const email = ref("");
|
||||
const name = ref("");
|
||||
const username = ref("");
|
||||
const password = ref("");
|
||||
const confirmPassword = ref("");
|
||||
|
||||
const errorMessage = ref("");
|
||||
const router = useRouter();
|
||||
|
||||
function register(){
|
||||
|
||||
if(password.value != confirmPassword.value){
|
||||
errorMessage.value = "Les contrasenyes no coincideixen";
|
||||
return;
|
||||
}
|
||||
|
||||
Api().post('/user/register',
|
||||
{
|
||||
name: name.value,
|
||||
username: username.value,
|
||||
email: email.value,
|
||||
password: password.value,
|
||||
}).then((response) => {
|
||||
const data = response.data;
|
||||
|
||||
if(data.error){
|
||||
errorMessage.value = data.msg;
|
||||
} else {
|
||||
errorMessage.value = "";
|
||||
conso
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1 class="title">Registra't</h1>
|
||||
|
||||
<ErrorMessage v-if="errorMessage">{{ errorMessage }}</ErrorMessage>
|
||||
|
||||
<form v-on:submit.prevent="register">
|
||||
<div class="form-field">
|
||||
<label for="name">Nom i cognoms</label>
|
||||
<input id="name-field" type="text" placeholder="Aran Roig" name="name" v-model="name" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="email">Correu electrònic</label>
|
||||
<input id="email-field" type="email" placeholder="correu@electronic.net" name="email" v-model="email" autocomplete="off" >
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="username">Nom d'usuari</label>
|
||||
<input id="username-field" type="text" placeholder="Introdueix un nom d'usuari..." name="username" v-model="username" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="password">Contrasenya</label>
|
||||
<input id="password-field" type="password" placeholder="Introdueix una contrasenya..." name="password" v-model="password" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="confirm-password">Confirma la teva contrasenya</label>
|
||||
<input id="confirm-password-field" type="password" placeholder="Repeteix la contrasenya..." name="confirm-password" v-model="confirmPassword" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button class="btn-primary">Registrar</button>
|
||||
</div>
|
||||
</form>
|
||||
<p class="centered">Ja tens un compte? <RouterLink to="/login" class="underline">Inicia sessió</RouterLink></p>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -11,6 +11,10 @@ import AccountSettingsWindow from '../windows/AccountSettingsWindow.vue'
|
||||
|
||||
import { Windows, ReloadRef } from '@/services/Windows';
|
||||
import DbWindow from '../windows/database/DbWindow.vue'
|
||||
import CampaignListWindow from '../windows/campaigns/CampaignListWindow.vue'
|
||||
import NewCampaignWindow from '../windows/campaigns/NewCampaignWindow.vue'
|
||||
import JoinCampaignWindow from '../windows/campaigns/JoinCampaignWindow.vue'
|
||||
import CampaignPreviewWindow from '@/views/windows/campaigns/CampaignPreviewWindow.vue'
|
||||
|
||||
// Gestionem ventanas
|
||||
const reload = ReloadRef();
|
||||
@ -24,6 +28,10 @@ const main_menu = windows.main_menu;
|
||||
const edit_profile = windows.edit_profile;
|
||||
const account_settings = windows.account_settings;
|
||||
const db_window = windows.db_window;
|
||||
const campaign_list = windows.campaign_list;
|
||||
const new_campaign = windows.new_campaign;
|
||||
const join_campaign = windows.join_campaign;
|
||||
const campaign_preview = windows.campaign_preview;
|
||||
|
||||
</script>
|
||||
|
||||
@ -36,6 +44,10 @@ const db_window = windows.db_window;
|
||||
<EditProfileWindow v-for="win in edit_profile" :key="win.id" :data="win"></EditProfileWindow>
|
||||
<AccountSettingsWindow v-for="win in account_settings" :key="win.id" :data="win"></AccountSettingsWindow>
|
||||
<DbWindow v-for="win in db_window" :key="win.id" :data="win"></DbWindow>
|
||||
<CampaignListWindow v-for="win in campaign_list" :key="win.id" :data="win"></CampaignListWindow>
|
||||
<NewCampaignWindow v-for="win in new_campaign" :key="win.id" :data="win"></NewCampaignWindow>
|
||||
<JoinCampaignWindow v-for="win in join_campaign" :key="win.id" :data="win"></JoinCampaignWindow>
|
||||
<CampaignPreviewWindow v-for="win in campaign_preview" :key="win.id" :data="win"></CampaignPreviewWindow>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
75
client/src/views/partials/CampaignEntry.vue
Normal file
75
client/src/views/partials/CampaignEntry.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<script setup>
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import Api from '@/services/Api'
|
||||
import { DisplayCampaign } from '@/services/Dragonroll'
|
||||
|
||||
const props = defineProps(['data']);
|
||||
const data = props.data;
|
||||
|
||||
const title = ref("");
|
||||
const last_session = ref("");
|
||||
|
||||
onMounted(() => {
|
||||
console.log(data);
|
||||
title.value = data.name;
|
||||
last_session.value = new Date(data.last_opened).toISOString().slice(0, 10);
|
||||
console.log(title);
|
||||
});
|
||||
|
||||
function ViewCampaign(){
|
||||
DisplayCampaign(data);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="campaign-entry-container">
|
||||
<div class="main-campaign-entry-container-inner">
|
||||
<img class="campaign-icon" src="img/def-avatar.jpg" draggable="false">
|
||||
<div class="campaign-info">
|
||||
<b>{{ title }}</b><br>Last session: <span>{{ last_session }}</span>
|
||||
</div>
|
||||
|
||||
<div class="campaign-user-actions">
|
||||
<button class="btn-primary button-small sound-click" v-on:click.prevent="ViewCampaign">View</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.button-small {
|
||||
height: 32px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.campaign-entry-container {
|
||||
background-color: var(--color-background-softer);
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.main-campaign-entry-container-inner {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.campaign-info {
|
||||
text-align: left;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.campaign-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.campaign-user-actions {
|
||||
margin-left: auto;
|
||||
}
|
||||
</style>
|
@ -10,7 +10,7 @@ import Api from '@/services/Api'
|
||||
import url from '@/services/BackendURL'
|
||||
|
||||
import useEmitter from '@/services/Emitter';
|
||||
import { ClearWindows, CreateWindow } from '../../services/Windows';
|
||||
import { ClearWindows, CreateWindow, CreateChildWindow } from '../../services/Windows';
|
||||
const emitter = useEmitter();
|
||||
|
||||
const username = ref("");
|
||||
@ -26,30 +26,16 @@ function retrieveAvatar(){
|
||||
function LogOut(){
|
||||
LogoutUser();
|
||||
|
||||
ClearWindows({type: "main_menu", title: "Dragonroll"});
|
||||
CreateWindow({
|
||||
type: "login",
|
||||
id: "login",
|
||||
title: "Login"
|
||||
});
|
||||
ClearWindows({type: "main_menu"});
|
||||
CreateWindow('login');
|
||||
}
|
||||
|
||||
function EditProfile(){
|
||||
CreateWindow({
|
||||
type: "edit_profile",
|
||||
id: "edit_profile",
|
||||
title: "Edit Profile",
|
||||
close: true
|
||||
});
|
||||
CreateChildWindow('main_menu', 'edit_profile');
|
||||
}
|
||||
|
||||
function EditSettings(){
|
||||
CreateWindow({
|
||||
type: "account_settings",
|
||||
id: "account_settings",
|
||||
title: "Dragonroll settings",
|
||||
close: true
|
||||
});
|
||||
CreateChildWindow('main_menu', 'account_settings');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@ -92,9 +78,9 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<div class="main-user-actions">
|
||||
<button class="btn-primary button-small" v-on:click.prevent="EditProfile">Edit profile</button>
|
||||
<button class="btn-primary button-small" v-on:click.prevent="EditSettings">Settings</button>
|
||||
<button class="btn-primary button-small" v-on:click.prevent="LogOut">Log out</button>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { GetWindowWithId } from '@/services/Windows';
|
||||
import { ClearWindow } from '../../services/Windows';
|
||||
|
||||
@ -24,15 +24,33 @@ function setupHandle() {
|
||||
hasBack.value = true;
|
||||
backFunction = win.back;
|
||||
}
|
||||
|
||||
// Setup sounds
|
||||
let currentWindowId = "window-wrapper-" + id;
|
||||
let currentWindow = document.getElementById(currentWindowId);
|
||||
let soundClicks = currentWindow.getElementsByClassName("sound-click");
|
||||
|
||||
|
||||
for (let i = 0; i < soundClicks.length; i++) {
|
||||
soundClicks[i].addEventListener("click", async (event) => {
|
||||
const audio = new Audio('/sounds/snap.wav');
|
||||
audio.type = "audio/wav"
|
||||
audio.play();
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function CloseButton(){
|
||||
const audio = new Audio('/sounds/close.wav');
|
||||
audio.type = "audio/wav"
|
||||
audio.play();
|
||||
ClearWindow(id)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
setupHandle
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@ onMounted(() => {
|
||||
successMessage.value = success;
|
||||
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {x: 700, y: 630});
|
||||
SetSize(id, {x: 450, y: 480});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
|
||||
@ -62,20 +62,12 @@ function login(){
|
||||
|
||||
function ShowRegister(){
|
||||
ClearWindows({type: "login"});
|
||||
CreateWindow({
|
||||
type: "register",
|
||||
id: "register",
|
||||
title: "Register"
|
||||
});
|
||||
CreateWindow('register');
|
||||
}
|
||||
|
||||
function ShowMainMenu(){
|
||||
ClearWindows({type: "login"});
|
||||
CreateWindow({
|
||||
type: "main_menu",
|
||||
id: "main_menu",
|
||||
title: "Dragonroll"
|
||||
});
|
||||
CreateWindow('main_menu');
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -97,7 +89,7 @@ function ShowMainMenu(){
|
||||
<input id="password-field" type="password" placeholder="Enter your password..." name="password" v-model="password" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button class="btn-primary">Log in</button>
|
||||
<button class="btn-primary sound-click">Log in</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -116,8 +108,6 @@ p {
|
||||
}
|
||||
|
||||
.window-wrapper {
|
||||
min-width: 700px;
|
||||
min-height: 630px;
|
||||
user-select: none;
|
||||
|
||||
display: flex;
|
||||
@ -125,17 +115,22 @@ p {
|
||||
}
|
||||
|
||||
.splash-image {
|
||||
width: 600px;
|
||||
height: 250px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
form {
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: left;
|
||||
flex-direction: column;
|
||||
justify-content: left;
|
||||
width: 600px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
label {
|
||||
|
@ -24,10 +24,12 @@ let title = data.title;
|
||||
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {x: 500, y: 600});
|
||||
SetSize(id, {x: 500, y: 540});
|
||||
ResetPosition(id, "center", emitter);
|
||||
});
|
||||
|
||||
// ???
|
||||
/*
|
||||
function OpenDatabase(){
|
||||
ClearWindow(id);
|
||||
CreateWindow({
|
||||
@ -44,13 +46,11 @@ function OpenDatabase(){
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
function OpenJoinCampaign(){
|
||||
ClearWindow(id);
|
||||
}
|
||||
|
||||
function OpenMyCampaigns(){
|
||||
function OpenCampaigns(){
|
||||
ClearWindow(id);
|
||||
CreateWindow('campaign_list');
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -65,12 +65,11 @@ function OpenMyCampaigns(){
|
||||
<h1>Main Menu</h1>
|
||||
|
||||
<div class="button-container">
|
||||
<button class="btn-primary button-expand" v-on:click="OpenMyCampaigns">My campaings</button>
|
||||
<button class="btn-primary button-expand" v-on:click="OpenJoinCampaign">Join existing campaign</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenCampaigns">Campaigns</button>
|
||||
<hr>
|
||||
<button class="btn-primary button-expand" v-on:click="OpenCollection">Your Collection</button>
|
||||
<button class="btn-primary button-expand" v-on:click="OpenLibrary">The Cosmic Library</button>
|
||||
<button class="btn-primary button-expand" v-on:click="OpenLibrary">Book Anvil</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenCollection">Your Collection</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenLibrary">The Cosmic Library</button>
|
||||
<button class="btn-primary button-expand sound-click" v-on:click="OpenLibrary">Book Anvil</button>
|
||||
</div>
|
||||
<VersionRender></VersionRender>
|
||||
</div>
|
||||
|
@ -29,7 +29,7 @@ let title = data.title;
|
||||
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {x: 700, y: 630});
|
||||
SetSize(id, {x: 450, y: 780});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
|
||||
@ -65,12 +65,7 @@ function register(){
|
||||
|
||||
function ShowLogin(msg){
|
||||
ClearWindows({type: "register"});
|
||||
CreateWindow({
|
||||
type: "login",
|
||||
id: "login",
|
||||
title: "Login",
|
||||
success: msg
|
||||
});
|
||||
CreateWindow('login', {success: msg});
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -106,7 +101,7 @@ function ShowLogin(msg){
|
||||
<input id="confirm-password-field" type="password" placeholder="Enter again your password..." name="confirm-password" v-model="confirmPassword" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button class="btn-primary">Register</button>
|
||||
<button class="btn-primary sound-click">Register</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -126,17 +121,11 @@ p {
|
||||
}
|
||||
|
||||
.window-wrapper {
|
||||
min-width: 700px;
|
||||
min-height: 630px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.window-content {
|
||||
overflow: auto;
|
||||
min-width: 700px;
|
||||
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -144,8 +133,7 @@ p {
|
||||
}
|
||||
|
||||
.splash-image {
|
||||
width: 600px;
|
||||
height: 250px;
|
||||
width: 400px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@ -155,7 +143,10 @@ p {
|
||||
align-items: left;
|
||||
flex-direction: column;
|
||||
justify-content: left;
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
|
135
client/src/views/windows/campaigns/CampaignListWindow.vue
Normal file
135
client/src/views/windows/campaigns/CampaignListWindow.vue
Normal file
@ -0,0 +1,135 @@
|
||||
<script setup>
|
||||
import { onMounted, onUpdated, ref } from 'vue';
|
||||
import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Windows';
|
||||
|
||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||
import { CreateWindow, CreateChildWindow } from '../../../services/Windows';
|
||||
|
||||
import Api from '@/services/Api.js'
|
||||
import CampaignEntry from '../../partials/CampaignEntry.vue';
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
const props = defineProps(['data']);
|
||||
const data = props.data;
|
||||
|
||||
const myCampaigns = ref([]);
|
||||
const otherCampaigns = ref([]);
|
||||
|
||||
let id = data.id;
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {x: 500, y: 680});
|
||||
ResetPosition(id, "center");
|
||||
|
||||
RefreshCampaigns();
|
||||
});
|
||||
|
||||
function CreateCampaign(){
|
||||
CreateChildWindow(id, 'new_campaign');
|
||||
}
|
||||
|
||||
function JoinCampaign(){
|
||||
CreateChildWindow(id, 'join_campaign')
|
||||
}
|
||||
|
||||
function RefreshCampaigns(){
|
||||
Api().get('/campaign/list').then((response) => {
|
||||
response.data.forEach((camp) => {
|
||||
if(camp.is_dm) {
|
||||
myCampaigns.value.push(camp.campaign);
|
||||
} else {
|
||||
otherCampaigns.value.push(camp.campaign);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||
|
||||
<div class="window-body">
|
||||
<!-- Body -->
|
||||
<div class="campaign-list-container">
|
||||
<div class="window-second-header">
|
||||
<h2>Your campaigns</h2>
|
||||
|
||||
<div class="campaign-list">
|
||||
<CampaignEntry v-for="camp in myCampaigns" :key="camp._id" :data="camp"></CampaignEntry>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="window-second-header">
|
||||
<h2>Other campaigns</h2>
|
||||
<div class="campaign-list">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="buttons-row">
|
||||
<button class="btn-primary button-row sound-click" v-on:click.prevent="CreateCampaign">Create campaign</button>
|
||||
<button class="btn-primary button-row sound-click" v-on:click.prevent="JoinCampaign">Join campaign</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.campaign-list {
|
||||
|
||||
}
|
||||
|
||||
.campaign-list-container {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.window-wrapper {
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.window-second-header {
|
||||
width: 100%;
|
||||
h2 {
|
||||
font-family: MrEavesRemake;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons-row {
|
||||
margin-top: auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: left;
|
||||
flex-direction: column;
|
||||
justify-content: left;
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
.window-body {
|
||||
max-height: 660px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
</style>
|
58
client/src/views/windows/campaigns/CampaignPreviewWindow.vue
Normal file
58
client/src/views/windows/campaigns/CampaignPreviewWindow.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<script setup>
|
||||
import { onMounted, onUpdated, ref } from 'vue';
|
||||
import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Windows';
|
||||
|
||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
const props = defineProps(['data']);
|
||||
const data = props.data;
|
||||
|
||||
let id = data.id;
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {x: 500, y: 380});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||
|
||||
<!-- Body -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.window-wrapper {
|
||||
min-width: 700px;
|
||||
min-height: 630px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.splash-image {
|
||||
width: 600px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: left;
|
||||
flex-direction: column;
|
||||
justify-content: left;
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
</style>
|
73
client/src/views/windows/campaigns/JoinCampaignWindow.vue
Normal file
73
client/src/views/windows/campaigns/JoinCampaignWindow.vue
Normal file
@ -0,0 +1,73 @@
|
||||
<script setup>
|
||||
import { onMounted, onUpdated, ref } from 'vue';
|
||||
import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Windows';
|
||||
|
||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
const props = defineProps(['data']);
|
||||
const data = props.data;
|
||||
|
||||
const code = ref("");
|
||||
|
||||
let id = data.id;
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {x: 300, y: 150});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||
|
||||
<!-- Body -->
|
||||
<form v-on:submit.prevent="JoinCampaign">
|
||||
<div class="form-field">
|
||||
<input id="username-field" type="text" placeholder="Enter campaign code..." name="code" v-model="code" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button class="btn-primary sound-click">Join</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.window-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.window-second-header {
|
||||
width: 100%;
|
||||
h2 {
|
||||
font-family: MrEavesRemake;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
align-items: left;
|
||||
flex-direction: column;
|
||||
justify-content: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
</style>
|
84
client/src/views/windows/campaigns/NewCampaignWindow.vue
Normal file
84
client/src/views/windows/campaigns/NewCampaignWindow.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<script setup>
|
||||
import { onMounted, onUpdated, ref } from 'vue';
|
||||
import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Windows';
|
||||
|
||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||
|
||||
import Api from '@/services/Api.js'
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
const props = defineProps(['data']);
|
||||
const data = props.data;
|
||||
|
||||
const campaignName = ref("");
|
||||
|
||||
let id = data.id;
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {x: 300, y: 150});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
|
||||
|
||||
function NewCampaign(){
|
||||
Api().post('/campaign/create', {
|
||||
name: campaignName.value
|
||||
}).then((response) => {
|
||||
console.log(response);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||
|
||||
<!-- Body -->
|
||||
<form v-on:submit.prevent="NewCampaign">
|
||||
<div class="form-field">
|
||||
<input id="username-field" type="text" placeholder="Enter campaign name..." name="campaignName" v-model="campaignName" autocomplete="off" >
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button class="btn-primary sound-click">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.window-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.window-second-header {
|
||||
width: 100%;
|
||||
h2 {
|
||||
font-family: MrEavesRemake;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
align-items: left;
|
||||
flex-direction: column;
|
||||
justify-content: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
</style>
|
23
server/models/Campaign.js
Normal file
23
server/models/Campaign.js
Normal file
@ -0,0 +1,23 @@
|
||||
const mongoose = require("mongoose");
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const CampaignSchema = new Schema({
|
||||
name: {type: String, required: true},
|
||||
creation_date: { type: Date, default: Date.now},
|
||||
last_opened: { type: Date, default: Date.now},
|
||||
invite_code: { type: String, unique: true },
|
||||
image: { type: String }
|
||||
});
|
||||
|
||||
CampaignSchema.statics.generateInvite = function() {
|
||||
let possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTVWXYZ0123456789";
|
||||
let cod = '';
|
||||
|
||||
for (let i = 0; i < 32; i++) {
|
||||
cod += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
}
|
||||
|
||||
return cod;
|
||||
}
|
||||
|
||||
module.exports = mongoose.model('Campaign', CampaignSchema);
|
10
server/models/CampaignUser.js
Normal file
10
server/models/CampaignUser.js
Normal file
@ -0,0 +1,10 @@
|
||||
const mongoose = require("mongoose")
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const CampaignUserSchema = new Schema({
|
||||
user: {type: mongoose.Types.ObjectId, ref: "User"},
|
||||
campaign: {type: mongoose.Types.ObjectId, ref: "Campaign"},
|
||||
is_dm: {type: Boolean, default: false}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('CampaignUser', CampaignUserSchema);
|
56
server/routes/campaign.js
Normal file
56
server/routes/campaign.js
Normal file
@ -0,0 +1,56 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
const passport = require('passport');
|
||||
const rateLimitMiddleware = require("../config/rate-limiter");
|
||||
|
||||
const Campaign = require("../models/Campaign");
|
||||
const CampaignUser = require("../models/CampaignUser");
|
||||
|
||||
const upload = require("../config/storage");
|
||||
|
||||
/*
|
||||
router.post('/register', passport.authenticate('jwt', {session: false}), rateLimitMiddleware, (req, res) => {
|
||||
});
|
||||
*/
|
||||
|
||||
router.post('/create', passport.authenticate('jwt', {session: false}), rateLimitMiddleware, (req, res) => {
|
||||
let {
|
||||
name
|
||||
} = req.body;
|
||||
|
||||
if(!(name)){
|
||||
res.json({
|
||||
status: "error",
|
||||
msg: "params"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the campaign
|
||||
let campaign = new Campaign({name});
|
||||
campaign.invite_code = Campaign.generateInvite();
|
||||
|
||||
campaign.save().then(campaign => {
|
||||
// Create relation with our user and set him as dm
|
||||
let campaignUser = new CampaignUser({
|
||||
user: req.user,
|
||||
campaign,
|
||||
is_dm: true
|
||||
});
|
||||
|
||||
campaignUser.save().then(campaignUser => {
|
||||
res.json(campaign);
|
||||
return
|
||||
}).catch((err) => {res.json({status: "error", msg: "internal"})});
|
||||
}).catch((err) => {res.json({status: "error", msg: "internal"})});
|
||||
});
|
||||
|
||||
router.get('/list', passport.authenticate('jwt', {session: false}), (req, res) => {
|
||||
CampaignUser.find({user: req.user}).populate("campaign").then((data) => {
|
||||
res.json(data);
|
||||
return;
|
||||
}).catch((err) => res.json({status: "error", msg: "internal"}));
|
||||
});
|
||||
|
||||
module.exports = router;
|
@ -54,6 +54,7 @@ app.use(cors());
|
||||
|
||||
// Routes (/ només)
|
||||
app.use('/user', require('./routes/user'));
|
||||
app.use('/campaign', require('./routes/campaign'));
|
||||
|
||||
// app.use('/users', require('./routes/users'));
|
||||
app.listen(PORT, () => {
|
||||
|
Loading…
Reference in New Issue
Block a user