More item types
This commit is contained in:
parent
dedbde13db
commit
73d10a7846
@ -7,7 +7,6 @@ const BookSchema = new Schema({
|
|||||||
description: { type: String },
|
description: { type: String },
|
||||||
system: {type: String, required: true},
|
system: {type: String, required: true},
|
||||||
image: { type: String },
|
image: { type: String },
|
||||||
contents: [ {type: mongoose.Types.ObjectId, ref: "Concept"} ],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = mongoose.model('Book', BookSchema);
|
module.exports = mongoose.model('Book', BookSchema);
|
@ -307,9 +307,50 @@ span.artifact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-element label {
|
.form-element label {
|
||||||
flex-grow: 1;
|
flex-grow: 0;
|
||||||
|
margin-right: 6px;
|
||||||
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-element.centered {
|
.form-element.centered {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grow {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.subsection.border:first-child {
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subsection.border {
|
||||||
|
border-left: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.subsection {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: left;
|
||||||
|
justify-content: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subsection.left {
|
||||||
|
align-items: left;
|
||||||
|
justify-content: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.subsection.right {
|
||||||
|
align-items: right;
|
||||||
|
justify-content: right;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.subsection.center {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
@ -71,8 +71,8 @@ function PopulateContext(val){
|
|||||||
|
|
||||||
animate(contextMenuElement, {
|
animate(contextMenuElement, {
|
||||||
opacity: [0, 1],
|
opacity: [0, 1],
|
||||||
translateY: [20, -2]
|
translateY: [-20, -2]
|
||||||
}, {delay: (elementNum / 2) * 0.1, duration: 0.25}).finished.then(() => {
|
}, {duration: 0.15}).finished.then(() => {
|
||||||
|
|
||||||
});
|
});
|
||||||
elementNum++;
|
elementNum++;
|
||||||
|
31
client/src/services/Utils.js
Normal file
31
client/src/services/Utils.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
function GetKey(from, key){
|
||||||
|
let k = key.split('.');
|
||||||
|
let obj = from;
|
||||||
|
for(let i = 0; i < k.length; i++){
|
||||||
|
if(typeof obj !== 'object'){
|
||||||
|
// We found a literal before ending!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(Object.keys(obj).includes(k[i])){
|
||||||
|
obj = obj[k[i]];
|
||||||
|
} else return;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetKey(from, key, value){
|
||||||
|
let k = key.split('.');
|
||||||
|
let obj = from;
|
||||||
|
for(let i = 0; i < k.length - 1; i++){
|
||||||
|
if(!Object.keys(obj).includes(k[i])){
|
||||||
|
obj[k[i]] = {};
|
||||||
|
}
|
||||||
|
obj = obj[k[i]];
|
||||||
|
}
|
||||||
|
obj[k[k.length - 1]] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
GetKey,
|
||||||
|
SetKey
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { AddContextMenu } from '@/services/ContextMenu';
|
import { AddContextMenu } from '@/services/ContextMenu';
|
||||||
import { AddTooltip } from '@/services/Tooltip';
|
import { AddTooltip } from '@/services/Tooltip';
|
||||||
|
import { GetKey } from '@/services/Utils';
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
|
|
||||||
const props = defineProps(['element', 'context', 'tooltip', 'icon']);
|
const props = defineProps(['element', 'context', 'tooltip', 'icon']);
|
||||||
@ -14,7 +15,8 @@ const icon = ref("icons/game-icons/ffffff/lorc/crossed-swords.svg")
|
|||||||
async function updateElement(){
|
async function updateElement(){
|
||||||
element.value = props.element;
|
element.value = props.element;
|
||||||
// Do whatever
|
// Do whatever
|
||||||
let desc = element.value.info.description;
|
let desc = undefined;
|
||||||
|
GetKey(element.value, "info.description", (val) => desc = val);
|
||||||
desc = desc ? marked.parse(desc) : '';
|
desc = desc ? marked.parse(desc) : '';
|
||||||
|
|
||||||
if(props.icon) icon.value = await props.icon(element.value);
|
if(props.icon) icon.value = await props.icon(element.value);
|
||||||
|
@ -11,6 +11,7 @@ const selected = ref(initialSelect);
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let context = [];
|
let context = [];
|
||||||
|
if(props.selected == undefined) selected.value = "undefined";
|
||||||
watch(() => props.selected, () => {
|
watch(() => props.selected, () => {
|
||||||
selected.value = props.selected;
|
selected.value = props.selected;
|
||||||
});
|
});
|
||||||
@ -21,7 +22,7 @@ onMounted(() => {
|
|||||||
action: () => {
|
action: () => {
|
||||||
HideContextMenu();
|
HideContextMenu();
|
||||||
selected.value = name;
|
selected.value = name;
|
||||||
selectCallback(name);
|
if(selectCallback) selectCallback(name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -34,12 +35,27 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="dropdown" ref="dropdown">
|
<div class="dropdown" ref="dropdown">
|
||||||
<span>{{ selected }}</span>
|
<span>{{ selected }}</span>
|
||||||
|
<img class="icon" src="/icons/iconoir/regular/nav-arrow-down.svg" draggable="false" ref="closeButton">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.dropdown {
|
.dropdown {
|
||||||
background-color: #181818;
|
flex-grow: 1;
|
||||||
padding: 5px;
|
display: flex;
|
||||||
|
|
||||||
|
background-color: var(--color-background-softer);
|
||||||
|
border: none;
|
||||||
|
padding: 4px 8px 4px 8px;
|
||||||
|
margin: 0 6px 0px 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--color-text);
|
||||||
|
transition: 300ms background-color;
|
||||||
|
border: solid 1px var(--color-border);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-left: auto;
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
8
client/src/views/partials/FormElement.vue
Normal file
8
client/src/views/partials/FormElement.vue
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="form-element">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -23,7 +23,9 @@ defineExpose({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.number-input {
|
.number-input {
|
||||||
max-width: 70px;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
width: 100px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -71,6 +71,7 @@ defineExpose({
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.tags-container {
|
.tags-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
|
@ -110,13 +110,5 @@
|
|||||||
"systems": {
|
"systems": {
|
||||||
"title": "Select a game system",
|
"title": "Select a game system",
|
||||||
"not-selected": "No game system selected"
|
"not-selected": "No game system selected"
|
||||||
},
|
|
||||||
"database": {
|
|
||||||
"title": "Database",
|
|
||||||
"tabs": {
|
|
||||||
"items": "Items",
|
|
||||||
"spells": "Spells",
|
|
||||||
"features": "Features"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,18 +16,13 @@ function Main(api){
|
|||||||
book: { type: "ObjectId", ref: "Book"}
|
book: { type: "ObjectId", ref: "Book"}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let entityModel = Api.createModel('entity', {
|
||||||
dndModule.router.get('/testing', (req, res) => {
|
|
||||||
/*
|
});
|
||||||
let item = itemModel.create({
|
|
||||||
name: "Test item!",
|
let characterModel = Api.createModel('character', {
|
||||||
type: "The test item"
|
|
||||||
})
|
});
|
||||||
*/
|
|
||||||
res.json({
|
|
||||||
status: "ok"
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
dndModule.router.get('/item/list', (req, res) => {
|
dndModule.router.get('/item/list', (req, res) => {
|
||||||
const campaign = req.query.campaign;
|
const campaign = req.query.campaign;
|
||||||
@ -50,7 +45,6 @@ function Main(api){
|
|||||||
res.json({status: "ok", item});
|
res.json({status: "ok", item});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
dndModule.router.get('/item/get', (req, res) => {
|
dndModule.router.get('/item/get', (req, res) => {
|
||||||
const campaign = req.query.campaign;
|
const campaign = req.query.campaign;
|
||||||
let id = req.query.id;
|
let id = req.query.id;
|
||||||
@ -59,7 +53,6 @@ function Main(api){
|
|||||||
res.json({status: "ok", concept});
|
res.json({status: "ok", concept});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
dndModule.router.put('/item/update', (req, res) => {
|
dndModule.router.put('/item/update', (req, res) => {
|
||||||
const campaign = req.query.campaign;
|
const campaign = req.query.campaign;
|
||||||
let id = req.query.id;
|
let id = req.query.id;
|
||||||
|
@ -68,7 +68,7 @@ function ConfigureBookmarks(){
|
|||||||
<img class="icon bookmark-icon" draggable="false" src="/icons/game-icons/ffffff/lorc/book-cover.svg">
|
<img class="icon bookmark-icon" draggable="false" src="/icons/game-icons/ffffff/lorc/book-cover.svg">
|
||||||
</div>
|
</div>
|
||||||
<div class="bookmark">
|
<div class="bookmark">
|
||||||
<img class="icon bookmark-icon" draggable="false" src="/icons/game-icons/ffffff/lorc/power-lightning.svg">
|
<img class="icon bookmark-icon" draggable="false" src="/icons/game-icons/ffffff/lorc/scroll-unfurled.svg">
|
||||||
</div>
|
</div>
|
||||||
<div class="bookmark">
|
<div class="bookmark">
|
||||||
<img class="icon bookmark-icon" draggable="false" src="/icons/game-icons/ffffff/lorc/feather.svg">
|
<img class="icon bookmark-icon" draggable="false" src="/icons/game-icons/ffffff/lorc/feather.svg">
|
||||||
|
@ -16,7 +16,7 @@ const PluginData = Global('dnd-5e').Data;
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
SetupHandle(id, handle);
|
SetupHandle(id, handle);
|
||||||
SetSize(id, {width: 250, height: 320});
|
SetSize(id, {width: 250, height: 410});
|
||||||
ResetPosition(id, "center");
|
ResetPosition(id, "center");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,6 +73,18 @@ function ConfirmSelection(){
|
|||||||
<span>Tool</span>
|
<span>Tool</span>
|
||||||
<input type="radio" name="selector" value="Tool">
|
<input type="radio" name="selector" value="Tool">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="radio-item">
|
||||||
|
<img class="icon" src="/icons/game-icons/000000/lorc/scroll-unfurled.svg">
|
||||||
|
<span>Spell</span>
|
||||||
|
<input type="radio" name="selector" value="Spell">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="radio-item">
|
||||||
|
<img class="icon" src="/icons/game-icons/000000/delapouite/round-star.svg">
|
||||||
|
<span>Feature</span>
|
||||||
|
<input type="radio" name="selector" value="Feature">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="btn-primary sound-click submit" v-on:click.prevent="ConfirmSelection">
|
<button class="btn-primary sound-click submit" v-on:click.prevent="ConfirmSelection">
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { marked } from "marked";
|
||||||
|
|
||||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||||
|
|
||||||
import { onMounted, ref, shallowRef, watch } from 'vue';
|
import { onMounted, ref, shallowRef, watch } from 'vue';
|
||||||
@ -7,6 +9,7 @@ import ConceptList from '@/views/partials/ConceptList.vue';
|
|||||||
import Tabs from '@/views/partials/Tabs.vue';
|
import Tabs from '@/views/partials/Tabs.vue';
|
||||||
import FixedBottomButtons from '@/views/partials/FixedBottomButtons.vue';
|
import FixedBottomButtons from '@/views/partials/FixedBottomButtons.vue';
|
||||||
import { Global } from '@/services/PluginGlobals';
|
import { Global } from '@/services/PluginGlobals';
|
||||||
|
import { GetKey } from '@/services/Utils.js';
|
||||||
|
|
||||||
import { FetchConcepts, GetConcepts } from './../data.js'
|
import { FetchConcepts, GetConcepts } from './../data.js'
|
||||||
|
|
||||||
@ -19,17 +22,34 @@ const Api = Global('dnd-5e').Api;
|
|||||||
const PluginData = Global('dnd-5e').Data;
|
const PluginData = Global('dnd-5e').Data;
|
||||||
|
|
||||||
let id = data.id;
|
let id = data.id;
|
||||||
const elements = shallowRef([]);
|
|
||||||
|
const weapons = shallowRef([]);
|
||||||
|
const equipment = shallowRef([]);
|
||||||
|
const consumables = shallowRef([]);
|
||||||
|
const containers = shallowRef([]);
|
||||||
|
const tools = shallowRef([]);
|
||||||
|
const spells = shallowRef([]);
|
||||||
|
const features = shallowRef([]);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
SetupHandle(id, handle);
|
SetupHandle(id, handle);
|
||||||
SetSize(id, {width: 700, height: 800});
|
SetSize(id, {width: 800, height: 800});
|
||||||
ResetPosition(id, "center");
|
ResetPosition(id, "center");
|
||||||
SetResizable(id, true);
|
SetResizable(id, true);
|
||||||
SetMinSize(id, {width: 350, height: 300});
|
SetMinSize(id, {width: 800, height: 300});
|
||||||
|
|
||||||
watch(GetConcepts, () => {
|
watch(GetConcepts, () => {
|
||||||
elements.value = GetConcepts();
|
let elements = GetConcepts();
|
||||||
|
weapons.value = elements.filter((e) => e.type == "Weapon");
|
||||||
|
equipment.value = elements.filter((e) => e.type == "Equipment");
|
||||||
|
consumables.value = elements.filter((e) => e.type == "Consumable");
|
||||||
|
containers.value = elements.filter((e) => e.type == "Container");
|
||||||
|
tools.value = elements.filter((e) => e.type == "Tool");
|
||||||
|
spells.value = elements.filter((e) => e.type == "Spell");
|
||||||
|
features.value = elements.filter((e) => e.type == "Feature");
|
||||||
|
|
||||||
|
console.log(elements);
|
||||||
|
console.log(elements);
|
||||||
});
|
});
|
||||||
|
|
||||||
FetchConcepts();
|
FetchConcepts();
|
||||||
@ -55,15 +75,18 @@ function ElementContext(element){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ElementTooltip(element){
|
function ElementTooltip(element){
|
||||||
|
let descHtml = GetKey(element, 'info.description');
|
||||||
|
if(descHtml) descHtml = marked.parse(descHtml);
|
||||||
|
else descHtml = '';
|
||||||
return `<div class='document item'>
|
return `<div class='document item'>
|
||||||
<h2>${element.name}</h2>
|
<h2>${element.name}</h2>
|
||||||
<img src='${element.info.icon}'></img>
|
<img src='${GetKey(element, "info.icon")}'></img>
|
||||||
<div class='document'>${element.info.description ?? ''}</div>
|
<div class='document'>${descHtml}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ElementIcon(element){
|
function ElementIcon(element){
|
||||||
return element.info ? element.info.icon : 'icons/game-icons/ffffff/lorc/crossed-swords.svg'
|
return GetKey(element, "info.icon") ? GetKey(element, "info.icon") : 'icons/game-icons/ffffff/lorc/crossed-swords.svg'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -74,13 +97,71 @@ function ElementIcon(element){
|
|||||||
|
|
||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
<Tabs :rows="[
|
<Tabs :rows="[
|
||||||
{id: 'items', value: 'database.tabs.items'},
|
{id: 'weapons', value: 'plugins.dnd-5e.database.tabs.weapons'},
|
||||||
{id: 'spells', value: 'database.tabs.spells'},
|
{id: 'equipment', value: 'plugins.dnd-5e.database.tabs.equipment'},
|
||||||
{id: 'features', value: 'database.tabs.features'}
|
{id: 'consumables', value: 'plugins.dnd-5e.database.tabs.consumables'},
|
||||||
|
{id: 'containers', value: 'plugins.dnd-5e.database.tabs.containers'},
|
||||||
|
{id: 'tools', value: 'plugins.dnd-5e.database.tabs.tools'},
|
||||||
|
{id: 'spells', value: 'plugins.dnd-5e.database.tabs.spells'},
|
||||||
|
{id: 'features', value: 'plugins.dnd-5e.database.tabs.features'},
|
||||||
]">
|
]">
|
||||||
<template #items>
|
<template #weapons>
|
||||||
<ConceptList
|
<ConceptList
|
||||||
:elements="elements"
|
:elements="weapons"
|
||||||
|
:open="OpenConcept"
|
||||||
|
:context="ElementContext"
|
||||||
|
:tooltip="ElementTooltip"
|
||||||
|
:icon="ElementIcon"
|
||||||
|
></ConceptList>
|
||||||
|
</template>
|
||||||
|
<template #equipment>
|
||||||
|
<ConceptList
|
||||||
|
:elements="equipment"
|
||||||
|
:open="OpenConcept"
|
||||||
|
:context="ElementContext"
|
||||||
|
:tooltip="ElementTooltip"
|
||||||
|
:icon="ElementIcon"
|
||||||
|
></ConceptList>
|
||||||
|
</template>
|
||||||
|
<template #consumables>
|
||||||
|
<ConceptList
|
||||||
|
:elements="consumables"
|
||||||
|
:open="OpenConcept"
|
||||||
|
:context="ElementContext"
|
||||||
|
:tooltip="ElementTooltip"
|
||||||
|
:icon="ElementIcon"
|
||||||
|
></ConceptList>
|
||||||
|
</template>
|
||||||
|
<template #containers>
|
||||||
|
<ConceptList
|
||||||
|
:elements="containers"
|
||||||
|
:open="OpenConcept"
|
||||||
|
:context="ElementContext"
|
||||||
|
:tooltip="ElementTooltip"
|
||||||
|
:icon="ElementIcon"
|
||||||
|
></ConceptList>
|
||||||
|
</template>
|
||||||
|
<template #tools>
|
||||||
|
<ConceptList
|
||||||
|
:elements="tools"
|
||||||
|
:open="OpenConcept"
|
||||||
|
:context="ElementContext"
|
||||||
|
:tooltip="ElementTooltip"
|
||||||
|
:icon="ElementIcon"
|
||||||
|
></ConceptList>
|
||||||
|
</template>
|
||||||
|
<template #spells>
|
||||||
|
<ConceptList
|
||||||
|
:elements="spells"
|
||||||
|
:open="OpenConcept"
|
||||||
|
:context="ElementContext"
|
||||||
|
:tooltip="ElementTooltip"
|
||||||
|
:icon="ElementIcon"
|
||||||
|
></ConceptList>
|
||||||
|
</template>
|
||||||
|
<template #features>
|
||||||
|
<ConceptList
|
||||||
|
:elements="features"
|
||||||
:open="OpenConcept"
|
:open="OpenConcept"
|
||||||
:context="ElementContext"
|
:context="ElementContext"
|
||||||
:tooltip="ElementTooltip"
|
:tooltip="ElementTooltip"
|
||||||
|
@ -10,9 +10,13 @@ import { AddContextMenu, HideContextMenu, ShowContextMenu } from '@/services/Con
|
|||||||
import Tabs from '@/views/partials/Tabs.vue';
|
import Tabs from '@/views/partials/Tabs.vue';
|
||||||
import MarkdownEditor from '@/views/partials/MarkdownEditor.vue';
|
import MarkdownEditor from '@/views/partials/MarkdownEditor.vue';
|
||||||
import Tags from '@/views/partials/Tags.vue';
|
import Tags from '@/views/partials/Tags.vue';
|
||||||
import NumberInput from '@/views/partials/NumberInput.vue';
|
import Input from '@/views/partials/Input.vue';
|
||||||
|
import { GetKey, SetKey } from '@/services/Utils.js';
|
||||||
|
|
||||||
import { Global } from '@/services/PluginGlobals';
|
import { Global } from '@/services/PluginGlobals';
|
||||||
|
import Dropdown from '@/views/partials/Dropdown.vue';
|
||||||
|
import FormElement from '@/views/partials/FormElement.vue';
|
||||||
|
|
||||||
const props = defineProps(['data']);
|
const props = defineProps(['data']);
|
||||||
const data = props.data;
|
const data = props.data;
|
||||||
const api = Global('dnd-5e').Api;
|
const api = Global('dnd-5e').Api;
|
||||||
@ -31,6 +35,7 @@ const properties = ref(null);
|
|||||||
const quantity = ref(null);
|
const quantity = ref(null);
|
||||||
const weight = ref(null);
|
const weight = ref(null);
|
||||||
const price = ref(null);
|
const price = ref(null);
|
||||||
|
const item_type_name = ref("");
|
||||||
|
|
||||||
function GenRarities(){
|
function GenRarities(){
|
||||||
let rarities = [];
|
let rarities = [];
|
||||||
@ -81,7 +86,7 @@ function Upload(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function SetParam(param, value){
|
function SetParam(param, value){
|
||||||
concept.value.info[param] = value;
|
SetKey(concept.value, `info.${param}`, value);
|
||||||
Upload();
|
Upload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,19 +105,17 @@ function PropertiesChanged(properties){
|
|||||||
function InitValues(){
|
function InitValues(){
|
||||||
let rarities = GenRarities();
|
let rarities = GenRarities();
|
||||||
let weapon_types = GenTypes(["", "Melee", "Ranged", "Martial Melee", "Martial Ranged", "Natural", "Improvised", "Siege Weapon"]);
|
let weapon_types = GenTypes(["", "Melee", "Ranged", "Martial Melee", "Martial Ranged", "Natural", "Improvised", "Siege Weapon"]);
|
||||||
|
|
||||||
if(!concept.value.data) concept.value.data = {};
|
|
||||||
if(!concept.value.info) concept.value.info = {};
|
|
||||||
|
|
||||||
if(concept.value.info.icon) icon_selector.value.icon = concept.value.info.icon;
|
icon_selector.value.icon = GetKey(concept.value, "info.icon");
|
||||||
if(concept.value.info.rarity) rarity.value.innerHTML = `<span class='important ${concept.value.info.rarity.replace(/\s+/g, '-').toLowerCase()}'>${concept.value.info.rarity}</span>`;
|
rarity.value.innerHTML = `<span class='important ${GetKey(concept.value, "info.rarity") ? GetKey(concept.value, "info.rarity").replace(/\s+/g, '-').toLowerCase() : ""}'>${GetKey(concept.value, "info.rarity")}</span>`;
|
||||||
if(concept.value.info.weapon_type) weaponType.value.innerHTML = `<span class='important'>${concept.value.info.weapon_type}</span>`;
|
weaponType.value.innerHTML = `<span class='important'>${GetKey(concept.value, "info.weapon_type")}</span>`;
|
||||||
if(concept.value.info.description) description.value.text = concept.value.info.description;
|
description.value.text = GetKey(concept.value, "info.description");
|
||||||
if(concept.value.info.properties) properties.value.selected = concept.value.info.properties;
|
properties.value.selected = GetKey(concept.value, "info.properties");
|
||||||
|
quantity.value.Set(GetKey(concept.value, "info.quantity"));
|
||||||
if(concept.value.info.quantity) quantity.value.Set(concept.value.info.quantity);
|
weight.value.Set(GetKey(concept.value, "info.weight"));
|
||||||
if(concept.value.info.weight) weight.value.Set(concept.value.info.weight);
|
price.value.Set(GetKey(concept.value, "info.price"));
|
||||||
if(concept.value.info.price) price.value.Set(concept.value.info.price);
|
item_type_name.value = GetKey(concept.value, "type");
|
||||||
|
item_name.value.innerHTML = GetKey(concept.value, "name");
|
||||||
|
|
||||||
quantity.value.OnUpdate((val) => SetParam('quantity', val));
|
quantity.value.OnUpdate((val) => SetParam('quantity', val));
|
||||||
weight.value.OnUpdate((val) => SetParam('weight', val));
|
weight.value.OnUpdate((val) => SetParam('weight', val));
|
||||||
@ -135,34 +138,32 @@ function InitValues(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
||||||
SetupHandle(id, handle);
|
SetupHandle(id, handle);
|
||||||
SetSize(id, {width: 600, height: 700});
|
SetSize(id, {width: 600, height: 700});
|
||||||
SetResizable(id, true);
|
SetResizable(id, true);
|
||||||
SetMinSize(id, {width: 400, height: 300});
|
SetMinSize(id, {width: 400, height: 300});
|
||||||
ResetPosition(id, "center");
|
ResetPosition(id, "center");
|
||||||
item_type.value = data.item_type;
|
|
||||||
|
|
||||||
if(data.item_create){
|
|
||||||
dndModule.router.post('/item/create', {}, {
|
|
||||||
data: {
|
|
||||||
type: data.item_type,
|
|
||||||
name: "New " + data.item_type
|
|
||||||
},
|
|
||||||
}).then(response => {
|
|
||||||
concept.value = response.data.concept;
|
|
||||||
InitValues();
|
|
||||||
|
|
||||||
}).catch(err => console.log(err));
|
|
||||||
} else {
|
|
||||||
// Get concept
|
|
||||||
GetConcept(data.item_id).then(response => {
|
|
||||||
concept.value = response.data.concept;
|
|
||||||
InitValues();
|
|
||||||
}).catch(err => console.log(err));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
item_type.value = data.item_type;
|
||||||
|
if(data.item_create){
|
||||||
|
dndModule.router.post('/item/create', {}, {
|
||||||
|
data: {
|
||||||
|
type: data.item_type,
|
||||||
|
name: "New " + data.item_type
|
||||||
|
},
|
||||||
|
}).then(response => {
|
||||||
|
concept.value = response.data.concept;
|
||||||
|
InitValues();
|
||||||
|
|
||||||
|
}).catch(err => console.log(err));
|
||||||
|
} else {
|
||||||
|
// Get concept
|
||||||
|
GetConcept(data.item_id).then(response => {
|
||||||
|
concept.value = response.data.concept;
|
||||||
|
InitValues();
|
||||||
|
}).catch(err => console.log(err));
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@ -174,10 +175,13 @@ onMounted(() => {
|
|||||||
<div class="item-header">
|
<div class="item-header">
|
||||||
<IconSelector :window="id" ref="icon_selector" :done="IconSelected"></IconSelector>
|
<IconSelector :window="id" ref="icon_selector" :done="IconSelected"></IconSelector>
|
||||||
<div class="header-info">
|
<div class="header-info">
|
||||||
<h1 contenteditable="true" spellcheck="false" ref="item_name">{{ concept.name }}</h1>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="grow subsection" ref="weaponType"></div>
|
<h1 class="grow subsection left" contenteditable="true" spellcheck="false" ref="item_name"></h1>
|
||||||
<div class="grow subsection" ref="rarity"></div>
|
<h1 class="subsection right">{{ item_type_name }}</h1>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="grow subsection center border" ref="weaponType"></div>
|
||||||
|
<div class="grow subsection center border" ref="rarity"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -189,18 +193,18 @@ onMounted(() => {
|
|||||||
<div class="description-container">
|
<div class="description-container">
|
||||||
<div class="description-sidebar">
|
<div class="description-sidebar">
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<div class="form-element">
|
<FormElement>
|
||||||
<label>{{$t('general.quantity')}}</label>
|
<label>{{$t('general.quantity')}}</label>
|
||||||
<NumberInput ref="quantity"></NumberInput>
|
<Input ref="quantity"></Input>
|
||||||
</div>
|
</FormElement>
|
||||||
<div class="form-element">
|
<FormElement>
|
||||||
<label>{{$t('general.weight')}}</label>
|
<label>{{$t('general.weight')}}</label>
|
||||||
<NumberInput ref="weight"></NumberInput>
|
<Input ref="weight"></Input>
|
||||||
</div>
|
</FormElement>
|
||||||
<div class="form-element">
|
<FormElement>
|
||||||
<label>{{$t('general.price')}}</label>
|
<label>{{$t('general.price')}}</label>
|
||||||
<NumberInput ref="price"></NumberInput>
|
<Input ref="price"></Input>
|
||||||
</div>
|
</FormElement>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
@ -210,8 +214,21 @@ onMounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
<template #details>
|
<template #details>
|
||||||
<h2 class="section">Properties</h2>
|
<h2 class="section">Properties</h2>
|
||||||
<Tags ref="properties" :items="['Amunnition','Finesse','Heavy','Light','Loading','Range','Reach','Special','Thrown','Two-Handed','Versatile']" :done="PropertiesChanged"></Tags>
|
<FormElement>
|
||||||
|
<label>Properties</label>
|
||||||
|
<Tags ref="properties" :items="['Amunnition','Finesse','Heavy','Light','Loading','Range','Reach','Special','Thrown','Two-Handed','Versatile']" :done="PropertiesChanged"></Tags>
|
||||||
|
</FormElement>
|
||||||
|
<h2 class="section">Usage</h2>
|
||||||
|
<FormElement>
|
||||||
|
<label>Range</label>
|
||||||
|
<Input></Input><label>/</label><Input></Input><Dropdown :options="['ft', 'm']" :selected="'ft'"></Dropdown>
|
||||||
|
</FormElement>
|
||||||
<h2 class="section">Damage</h2>
|
<h2 class="section">Damage</h2>
|
||||||
|
<FormElement>
|
||||||
|
<label>Damage</label>
|
||||||
|
<Dropdown :options="['None','Acid','Bludgeoning','Cold','Fire','Force','Lightning','Necrotic','Piercing','Poison','Psychic','Radiant','Slashing','Thunder','Healing','Healing (Temp)']"></Dropdown>
|
||||||
|
<Input></Input>
|
||||||
|
</FormElement>
|
||||||
</template>
|
</template>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
@ -245,7 +262,7 @@ h2.section {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.description-sidebar {
|
.description-sidebar {
|
||||||
min-width: 200px;
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
@ -285,10 +302,6 @@ h2.section {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grow {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-wrapper {
|
.window-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -296,15 +309,4 @@ h2.section {
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subsection {
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-right: 1px solid var(--color-border);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
{
|
{
|
||||||
"test": "Test"
|
"database": {
|
||||||
|
"title": "Database",
|
||||||
|
"tabs": {
|
||||||
|
"weapons": "Weapons",
|
||||||
|
"equipment": "Equipment",
|
||||||
|
"consumables": "Consumables",
|
||||||
|
"containers": "Containers",
|
||||||
|
"tools": "Tools",
|
||||||
|
"spells": "Spells",
|
||||||
|
"features": "Features"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user