Campaign description

This commit is contained in:
BinarySandia04 2024-09-26 01:15:53 +02:00
parent 80ede11f7c
commit be6d4fda26
13 changed files with 217 additions and 45 deletions

View File

@ -50,7 +50,8 @@ module.exports = io => {
console.log(socket.user.username + " ha entrado!");
SetPlayerProperty(campaignId, socket.user._id, "online", true);
io.to(socket.campaign).emit('update-players', sessions[campaignId].players)
// io.to(socket.campaign).emit('update-players', sessions[campaignId].players)
socket.emit('init-info', {players: sessions[campaignId].players})
// console.log(JSON.stringify(sessions[campaignId], null, 4));
}

View File

@ -3,6 +3,7 @@ const Schema = mongoose.Schema;
const CampaignSchema = new Schema({
name: {type: String, required: true},
description: {type: String},
system: {type: String, required: true},
creation_date: { type: Date, default: Date.now},
last_opened: { type: Date, default: Date.now},

View File

@ -99,4 +99,27 @@ router.get('/players', (req, res) => {
}).catch((err) => res.json({status: "error", msg: "not-found"}));
});
router.put('/update', (req, res) => {
CampaignUser.find({campaign: req.query.campaign}).then((data) => {
if(data.is_dm){
let {
name,
description
} = req.body.campaign;
Campaign.findOneAndUpdate({_id: req.query.campaign}, {
name,
description
}).then((campaign) => {
res.json({stauts: "ok", campaign})
});
return;
}
res.json({
status: "error",
msg: "forbidden"
})
});
});
module.exports = router;

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

View File

@ -20,6 +20,7 @@
"marked": "^9.1.6",
"marked-katex-extension": "^4.0.1",
"mitt": "^3.0.1",
"motion": "^10.18.0",
"prismjs": "^1.29.0",
"serve": "^14.2.3",
"socket.io-client": "^4.7.5",
@ -1193,6 +1194,70 @@
"dev": true,
"license": "MIT"
},
"node_modules/@motionone/animation": {
"version": "10.18.0",
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz",
"integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==",
"license": "MIT",
"dependencies": {
"@motionone/easing": "^10.18.0",
"@motionone/types": "^10.17.1",
"@motionone/utils": "^10.18.0",
"tslib": "^2.3.1"
}
},
"node_modules/@motionone/dom": {
"version": "10.18.0",
"resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz",
"integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==",
"license": "MIT",
"dependencies": {
"@motionone/animation": "^10.18.0",
"@motionone/generators": "^10.18.0",
"@motionone/types": "^10.17.1",
"@motionone/utils": "^10.18.0",
"hey-listen": "^1.0.8",
"tslib": "^2.3.1"
}
},
"node_modules/@motionone/easing": {
"version": "10.18.0",
"resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz",
"integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==",
"license": "MIT",
"dependencies": {
"@motionone/utils": "^10.18.0",
"tslib": "^2.3.1"
}
},
"node_modules/@motionone/generators": {
"version": "10.18.0",
"resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz",
"integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==",
"license": "MIT",
"dependencies": {
"@motionone/types": "^10.17.1",
"@motionone/utils": "^10.18.0",
"tslib": "^2.3.1"
}
},
"node_modules/@motionone/types": {
"version": "10.17.1",
"resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz",
"integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==",
"license": "MIT"
},
"node_modules/@motionone/utils": {
"version": "10.18.0",
"resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz",
"integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==",
"license": "MIT",
"dependencies": {
"@motionone/types": "^10.17.1",
"hey-listen": "^1.0.8",
"tslib": "^2.3.1"
}
},
"node_modules/@mrmlnc/readdir-enhanced": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@ -7521,6 +7586,12 @@
"he": "bin/he"
}
},
"node_modules/hey-listen": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==",
"license": "MIT"
},
"node_modules/highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
@ -9226,6 +9297,18 @@
"resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz",
"integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg=="
},
"node_modules/motion": {
"version": "10.18.0",
"resolved": "https://registry.npmjs.org/motion/-/motion-10.18.0.tgz",
"integrity": "sha512-MVAZZmwM/cp77BrNe1TxTMldxRPjwBNHheU5aPToqT4rJdZxLiADk58H+a0al5jKLxkB0OdgNq6DiVn11cjvIQ==",
"license": "MIT",
"dependencies": {
"@motionone/animation": "^10.18.0",
"@motionone/dom": "^10.18.0",
"@motionone/types": "^10.17.1",
"@motionone/utils": "^10.18.0"
}
},
"node_modules/mrmime": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
@ -12844,7 +12927,6 @@
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
"dev": true,
"license": "0BSD"
},
"node_modules/type-check": {

View File

@ -21,6 +21,7 @@
"marked": "^9.1.6",
"marked-katex-extension": "^4.0.1",
"mitt": "^3.0.1",
"motion": "^10.18.0",
"prismjs": "^1.29.0",
"serve": "^14.2.3",
"socket.io-client": "^4.7.5",

View File

@ -11,7 +11,10 @@
"username": "Username",
"password": "Password",
"password-confirm": "Confirm your password",
"register": "Register"
"register": "Register",
"quantity": "Quantity",
"weight": "Weight",
"price": "Price"
},
"placeholders": {
"name": "John Doe",

View File

@ -11,7 +11,10 @@
"username": "Nombre de usuario",
"password": "Contraseña",
"password-confirm": "Confirma tu contraseña",
"register": "Registrar-se"
"register": "Registrar-se",
"quantity": "Quantity",
"weight": "Weight",
"price": "Price"
},
"placeholders": {
"name": "John Doe",

View File

@ -28,18 +28,27 @@ function Disconnect(){
}
function DisplayCampaign(data = currentCampaign){
function DisplayCampaign(data = _currentCampaign){
ClearAll();
CreateWindow('campaign_preview', {campaign: data});
}
socket.on('update-players', data => {
_UpdatePlayers(data)
})
socket.on('init-info', data => {
_UpdatePlayers(data.players);
DisplayCampaign();
})
function _UpdatePlayers(data){
_players.value = [];
Object.keys(data).forEach((key) => {
_players.value.push(data[key]);
if(GetUser()._id == data[key].user._id) _currentPlayer = data[key];
});
})
}
export {
_currentCampaign,

View File

@ -23,7 +23,7 @@ onMounted(() => {
function ViewCampaign(){
ConnectToCampaign(data);
DisplayCampaign(data);
// DisplayCampaign(data);
}
</script>

View File

@ -2,11 +2,13 @@
import { onMounted, ref, watch } from 'vue';
import { marked } from "https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js";
const props = defineProps(['done']);
const props = defineProps(['done', 'editable']);
import IconButton from '../partials/game/IconButton.vue';
const editing = ref(false);
const isEditable = ref(true);
const editor = ref(null);
const preview = ref(null);
const text = ref("");
@ -21,12 +23,26 @@ function PreviewContent(){
preview.value.innerHTML = marked.parse(editor.value.value);
}
function UpdateEditable(val){
if(val) {
isEditable.value = true;
} else {
isEditable.value = false;
editing.value = false;
}
}
onMounted(() => {
watch(text, () => {
editor.value.value = text.value;
preview.value.innerHTML = marked.parse(editor.value.value);
});
UpdateEditable(props.editable);
watch(() => props.editable, () => {
UpdateEditable(props.editable);
})
editor.value.addEventListener("change", () => {
props.done(editor.value.value);
});
@ -44,18 +60,18 @@ defineExpose({
<div class="markdown-editor">
<div class="editor-content">
<div v-show="!editing" class="preview">
<div class="document preview" ref="preview">
<div class="document" ref="preview">
</div>
<div class="fixed-bottom-buttons">
<IconButton icon="/icons/iconoir/regular/edit-pencil.svg" :action="EditContent"></IconButton>
<IconButton v-show="isEditable" icon="/icons/iconoir/regular/edit-pencil.svg" :action="EditContent"></IconButton>
</div>
</div>
<div v-show="editing" class="editor">
<textarea class="editing" ref="editor"></textarea>
<div class="fixed-bottom-buttons">
<IconButton icon="/icons/iconoir/solid/eye.svg" :action="PreviewContent"></IconButton>
<IconButton v-show="isEditable" icon="/icons/iconoir/solid/eye.svg" :action="PreviewContent"></IconButton>
</div>
</div>
</div>
@ -68,7 +84,28 @@ defineExpose({
height: 100%;
}
.document, .preview {
width: 100%;
max-width: 100%;
height: 100%;
max-height: 100%;
overflow-y: auto;
overflow-x: auto;
}
.document {
padding: 10px;
max-width: fit-content;
position: absolute;
}
.editor-content {
display: flex;
width: 100%;
}
.editing {
resize: none;
background-color: var(--color-background);
}
@ -86,9 +123,4 @@ defineExpose({
z-index: 2;
display: flex;
}
.preview {
padding: 8px 0 8px 8px;
overflow-y: auto;
height: 100%;
}
</style>

View File

@ -1,10 +1,10 @@
<script setup>
import { onMounted, onUpdated, ref } from 'vue';
import { onMounted, onUpdated, ref, toRaw, watch } from 'vue';
import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Windows';
import WindowHandle from '@/views/partials/WindowHandle.vue';
import PlayerList from '../../partials/PlayerList.vue';
import { DisplayToast, GetClient } from '../../../services/Dragonroll';
import { DisplayToast, GetPlayerList } from '@/services/Dragonroll';
import CampaignBookList from '../../partials/books/CampaignBookList.vue';
import { ClearAll, ClearWindow, CreateWindow, SetMinSize, SetResizable } from '../../../services/Windows';
import { LaunchGame } from '../../../services/Game';
@ -14,8 +14,10 @@ import GameSystem from '@/views/partials/GameSystem.vue'
import { GetModule } from '../../../services/Modules';
import { AddTooltip } from '../../../services/Tooltip';
import { Disconnect } from '../../../services/Campaign';
import MarkdownEditor from '@/views/partials/MarkdownEditor.vue';
import { useI18n } from 'vue-i18n';
import { GetClient } from '../../../services/Dragonroll';
const {t} = useI18n();
const handle = ref(null);
@ -31,25 +33,6 @@ const copy_code_button = ref(null);
const container = ref(null);
let id = data.id;
onMounted(() => {
SetupHandle(id, handle);
SetSize(id, {width: 800, height: 750});
SetResizable(id, true);
SetMinSize(id, {width: 600, height: 500});
hide_chat.value = true;
ResetPosition(id, "center");
hide_start.value = data.hide_start;
AddSound(container.value)
campaign_title.value.style.backgroundColor = GetModule(data.campaign.system).color ? GetModule(data.campaign.system).color : "#1f1f1f";
AddTooltip(copy_code_button.value, `<p>${t('campaigns.preview.copy-explain')}</p>`, {max_width: 300})
});
function CopyCode(){
navigator.clipboard.writeText(GetCampaign().invite_code);
@ -67,6 +50,30 @@ function Exit(){
CreateWindow('campaign_list');
}
const description_editable = ref(false);
onMounted(() => {
if(GetClient().is_dm) description_editable.value = true;
SetupHandle(id, handle);
SetSize(id, {width: 800, height: 750});
SetResizable(id, true);
SetMinSize(id, {width: 800, height: 650});
hide_chat.value = true;
ResetPosition(id, "center");
hide_start.value = data.hide_start;
AddSound(container.value)
campaign_title.value.style.backgroundColor = GetModule(data.campaign.system).color ? GetModule(data.campaign.system).color : "#1f1f1f";
AddTooltip(copy_code_button.value, `<p>${t('campaigns.preview.copy-explain')}</p>`, {max_width: 300})
});
</script>
@ -90,8 +97,10 @@ function Exit(){
<div class="campaign-main-container">
<div class="campaign-main-container-scroll">
<GameSystem :data="GetModule(data.campaign.system)"></GameSystem>
<h2>Books</h2>
<CampaignBookList class="small-book-list"></CampaignBookList>
<div class="description">
<MarkdownEditor ref="description" :done="DescriptionChanged" :editable="description_editable"></MarkdownEditor>
</div>
<!-- <CampaignBookList class="small-book-list"></CampaignBookList> -->
</div>
</div>
<div class="buttons-row">
@ -109,6 +118,13 @@ function Exit(){
<style scoped lang="scss">
.description {
position: relative;
height: calc(100% - 55px);
width: 100%;
flex-grow: 0;
}
.small-book-list {
margin: 20px;
overflow: auto;
@ -116,13 +132,13 @@ function Exit(){
.campaign-main-container-scroll {
overflow-y: scroll;
height: 100%;
max-height: 520px;
height: calc(100% - 10px);
}
.campaign-main-container {
height: 100%;
flex-grow: 1;
h2 {
text-align: left;
margin-left: 20px;
@ -136,7 +152,6 @@ function Exit(){
font-weight: normal;
text-align: left;
padding: 20px;
margin-bottom: 30px;
}
.button-row {
@ -145,7 +160,7 @@ function Exit(){
.campaign-preview-container {
width: 100%;
height: 100%;
height: calc(100% - 24px);
display: flex;
flex-direction: row;
}
@ -158,7 +173,7 @@ function Exit(){
background-color: var(--color-background-soft);
border-right: 1px solid var(--color-border);
flex-grow: 1;
min-width: 100px;
min-width: 250px;
max-width: 300px;
}
@ -166,7 +181,9 @@ function Exit(){
background-color: var(--color-background-semisoft);
display: flex;
flex-direction: column;
flex-grow: 3;
max-width: 100%;
}
&.right {

View File

@ -199,7 +199,7 @@ onMounted(() => {
</div>
</div>
<div class="description">
<MarkdownEditor ref="description" :done="DescriptionChanged"></MarkdownEditor>
<MarkdownEditor ref="description" :done="DescriptionChanged" :editable="true"></MarkdownEditor>
</div>
</div>
</template>