Campaign description
This commit is contained in:
parent
80ede11f7c
commit
be6d4fda26
@ -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));
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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;
|
BIN
backend/uploads/image-1727299238153
Normal file
BIN
backend/uploads/image-1727299238153
Normal file
Binary file not shown.
After Width: | Height: | Size: 210 KiB |
84
client/package-lock.json
generated
84
client/package-lock.json
generated
@ -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": {
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -23,7 +23,7 @@ onMounted(() => {
|
||||
|
||||
function ViewCampaign(){
|
||||
ConnectToCampaign(data);
|
||||
DisplayCampaign(data);
|
||||
// DisplayCampaign(data);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -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>
|
@ -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 {
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user