More thinngeijidjioashdisa

This commit is contained in:
BinarySandia04 2024-08-03 22:54:58 +02:00
parent 34a8e1d120
commit 1991fd8f02
26 changed files with 714 additions and 180 deletions

View File

@ -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>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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;

View File

@ -0,0 +1,12 @@
import { ClearAll, ClearWindow, CreateWindow } from './Windows';
function DisplayCampaign(data){
ClearAll();
CreateWindow('campaign_preview', {
title: data.name
});
}
export {
DisplayCampaign
};

View File

@ -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
}

View File

@ -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');
}
);

View File

@ -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>

View File

@ -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>

View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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 {

View File

@ -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>

View File

@ -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 {

View 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>

View 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>

View 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>

View 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
View 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);

View 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
View 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;

View File

@ -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, () => {