From 25e6b19b49a7eecc73f40ebc36091f3a480c50ed Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Sun, 15 Jan 2023 01:17:00 +0200 Subject: [PATCH 1/3] Progress on tabletop UI design --- app/imports/api/engine/loadCreatures.js | 26 +- app/imports/api/tabletop/map/TabletopMap.vue | 89 ---- .../client/ui/components/RollPopup.vue | 5 +- .../ui/creature/character/CharacterSheet.vue | 23 +- .../ui/dialogStack/DialogComponentIndex.js | 8 +- app/imports/client/ui/layouts/Sidebar.vue | 3 +- .../actions/AttributeConsumedView.vue | 9 +- .../components/actions/ItemConsumedView.vue | 36 +- app/imports/client/ui/router.js | 2 - app/imports/client/ui/styles/cardColors.css | 10 +- .../ui}/tabletop/CharacterSheetDialog.vue | 50 ++- .../client/ui/tabletop/TabletopActionCard.vue | 388 ++++++++++++++++++ .../ui/tabletop/TabletopActionCards.vue | 49 --- .../client/ui/tabletop/TabletopComponent.vue | 91 ++-- .../ui/tabletop/TabletopCreatureCard.vue | 45 +- .../client/ui/tabletop/TabletopLog.vue | 17 +- .../client/ui/tabletop/TabletopMap.vue | 86 +++- app/imports/server/publications/tabletops.js | 36 +- app/package-lock.json | 14 +- app/package.json | 3 +- 20 files changed, 700 insertions(+), 290 deletions(-) delete mode 100644 app/imports/api/tabletop/map/TabletopMap.vue rename app/imports/{api => client/ui}/tabletop/CharacterSheetDialog.vue (51%) create mode 100644 app/imports/client/ui/tabletop/TabletopActionCard.vue delete mode 100644 app/imports/client/ui/tabletop/TabletopActionCards.vue diff --git a/app/imports/api/engine/loadCreatures.js b/app/imports/api/engine/loadCreatures.js index aa036a37..829033cb 100644 --- a/app/imports/api/engine/loadCreatures.js +++ b/app/imports/api/engine/loadCreatures.js @@ -10,15 +10,17 @@ export const loadedCreatures = new Map(); // creatureId => {creature, properties export function loadCreature(creatureId, subscription) { if (!creatureId) throw 'creatureId is required'; let creature = loadedCreatures.get(creatureId); + if (!creature || !creature.subs.has(subscription)) { + subscription.onStop(() => { + unloadCreature(creatureId, subscription); + }); + } if (loadedCreatures.has(creatureId)) { creature.subs.add(subscription); } else { creature = new LoadedCreature(subscription, creatureId); loadedCreatures.set(creatureId, creature); } - subscription.onStop(() => { - unloadCreature(creatureId, subscription); - }); } function unloadCreature(creatureId, subscription) { @@ -43,7 +45,7 @@ export function getSingleProperty(creatureId, propertyId) { const prop = CreatureProperties.findOne({ _id: propertyId, 'ancestors.id': creatureId, - 'removed': {$ne: true}, + 'removed': { $ne: true }, }, { sort: { order: 1 }, }); @@ -61,7 +63,7 @@ export function getProperties(creatureId) { // console.time(`Cache miss on creature properties: ${creatureId}`) const props = CreatureProperties.find({ 'ancestors.id': creatureId, - 'removed': {$ne: true}, + 'removed': { $ne: true }, }, { sort: { order: 1 }, }).fetch(); @@ -73,7 +75,7 @@ export function getPropertiesOfType(creatureId, propType) { if (loadedCreatures.has(creatureId)) { const creature = loadedCreatures.get(creatureId); const props = [] - for (const prop of creature.properties.values()){ + for (const prop of creature.properties.values()) { if (prop.type === propType) { props.push(prop); } @@ -97,7 +99,7 @@ export function getCreature(creatureId) { if (loadedCreatures.has(creatureId)) { const loadedCreature = loadedCreatures.get(creatureId); const creature = loadedCreature.creature; - if (creature) { + if (creature) { const cloneCreature = EJSON.clone(creature); return cloneCreature; } @@ -118,7 +120,7 @@ export function getVariables(creatureId) { } } // console.time(`Cache miss on variables: ${creatureId}`); - const variables = CreatureVariables.findOne({_creatureId: creatureId}); + const variables = CreatureVariables.findOne({ _creatureId: creatureId }); // console.timeEnd(`Cache miss on variables: ${creatureId}`); return variables; } @@ -148,7 +150,7 @@ export function getProperyAncestors(creatureId, propertyId) { // Fetch from database return CreatureProperties.find({ _id: { $in: ancestorIds }, - removed: {$ne: true}, + removed: { $ne: true }, }, { sort: { order: 1 }, }).fetch(); @@ -164,7 +166,7 @@ export function getPropertyDecendants(creatureId, propertyId) { if (loadedCreatures.has(creatureId)) { const creature = loadedCreatures.get(creatureId); const props = []; - for(const prop of creature.properties.values()){ + for (const prop of creature.properties.values()) { if (prop.ancestors[expectedAncestorPostition]?.id === propertyId) { props.push(prop); } @@ -216,7 +218,7 @@ class LoadedCreature { compute(); }, }); - + // Observe the creature itself self.creatureObserver = Creatures.find({ _id: creatureId, @@ -239,7 +241,7 @@ class LoadedCreature { self.variablesObserver = CreatureVariables.find({ _creatureId: creatureId, }, { - fields: { _creatureId: 0}, + fields: { _creatureId: 0 }, }).observeChanges({ added(id, fields) { fields._id = id; diff --git a/app/imports/api/tabletop/map/TabletopMap.vue b/app/imports/api/tabletop/map/TabletopMap.vue deleted file mode 100644 index 0c87c5ae..00000000 --- a/app/imports/api/tabletop/map/TabletopMap.vue +++ /dev/null @@ -1,89 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/imports/client/ui/components/RollPopup.vue b/app/imports/client/ui/components/RollPopup.vue index f9f20f66..a4521339 100644 --- a/app/imports/client/ui/components/RollPopup.vue +++ b/app/imports/client/ui/components/RollPopup.vue @@ -12,8 +12,8 @@ @@ -87,6 +87,7 @@ export default { type: Number, default: undefined, }, + noClick: Boolean, }, data(){return { open: false, diff --git a/app/imports/client/ui/creature/character/CharacterSheet.vue b/app/imports/client/ui/creature/character/CharacterSheet.vue index 75f4cbd8..568ebe79 100644 --- a/app/imports/client/ui/creature/character/CharacterSheet.vue +++ b/app/imports/client/ui/creature/character/CharacterSheet.vue @@ -30,17 +30,17 @@
@@ -68,11 +68,10 @@ -
@@ -164,7 +163,9 @@ export default { type: String, required: true, }, + embedded: Boolean, }, + // @ts-ignore reactiveProvide: { name: 'context', include: ['creatureId', 'editPermission'], @@ -250,7 +251,11 @@ export default { diff --git a/app/imports/client/ui/dialogStack/DialogComponentIndex.js b/app/imports/client/ui/dialogStack/DialogComponentIndex.js index 87530412..bb491fec 100644 --- a/app/imports/client/ui/dialogStack/DialogComponentIndex.js +++ b/app/imports/client/ui/dialogStack/DialogComponentIndex.js @@ -1,6 +1,7 @@ // Load commonly used dialogs immediately import AddCreaturePropertyDialog from '/imports/client/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue'; import CharacterCreationDialog from '/imports/client/ui/creature/character/CharacterCreationDialog.vue'; +import CharacterSheetDialog from '/imports/client/ui/tabletop/CharacterSheetDialog.vue'; import CastSpellWithSlotDialog from '/imports/client/ui/properties/components/spells/CastSpellWithSlotDialog.vue'; import CreatureFormDialog from '/imports/client/ui/creature/CreatureFormDialog.vue'; import CreaturePropertyCreationDialog from '/imports/client/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue'; @@ -8,9 +9,9 @@ import CreaturePropertyDialog from '/imports/client/ui/creature/creatureProperti import CreaturePropertyFromLibraryDialog from '/imports/client/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue'; import CreatureRootDialog from '/imports/client/ui/creature/character/CreatureRootDialog.vue'; import DeleteConfirmationDialog from '/imports/client/ui/dialogStack/DeleteConfirmationDialog.vue'; -import ExperienceInsertDialog from '/imports/client/ui/creature/experiences/ExperienceInsertDialog.vue'; -import ExperienceListDialog from '/imports/client/ui/creature/experiences/ExperienceListDialog.vue'; -import HelpDialog from '/imports/client/ui/dialogStack/HelpDialog.vue'; +import ExperienceInsertDialog from '/imports/client/ui/creature/experiences/ExperienceInsertDialog.vue'; +import ExperienceListDialog from '/imports/client/ui/creature/experiences/ExperienceListDialog.vue'; +import HelpDialog from '/imports/client/ui/dialogStack/HelpDialog.vue'; import LevelUpDialog from '/imports/client/ui/creature/slots/LevelUpDialog.vue'; import SelectLibraryNodeDialog from '/imports/client/ui/library/SelectLibraryNodeDialog.vue'; import SlotFillDialog from '/imports/client/ui/creature/slots/SlotFillDialog.vue'; @@ -37,6 +38,7 @@ export default { ArchiveDialog, CastSpellWithSlotDialog, CharacterCreationDialog, + CharacterSheetDialog, CreatureFormDialog, CreaturePropertyCreationDialog, CreaturePropertyDialog, diff --git a/app/imports/client/ui/layouts/Sidebar.vue b/app/imports/client/ui/layouts/Sidebar.vue index 1b893f37..bf9d0562 100644 --- a/app/imports/client/ui/layouts/Sidebar.vue +++ b/app/imports/client/ui/layouts/Sidebar.vue @@ -80,6 +80,7 @@ export default { components: { CreatureFolderList }, + // @ts-ignore meteor: { $subscribe: { 'characterList': [], @@ -97,7 +98,7 @@ export default { { title: 'Home', icon: 'mdi-home', to: '/' }, { title: 'Characters', icon: 'mdi-account-group', to: '/character-list', requireLogin: true }, { title: 'Library', icon: 'mdi-library-shelves', to: '/library', requireLogin: true }, - //{title: 'Tabletops', icon: 'api', to: '/tabletops', requireLogin: true}, + {title: 'Tabletops', icon: 'mdi-table-furniture', to: '/tabletops', requireLogin: true}, //{title: 'Friends', icon: 'people', to: '/friends', requireLogin: true}, { title: 'Files', icon: 'mdi-file-multiple', to: '/my-files' }, { title: 'Feedback', icon: 'mdi-bug', to: '/feedback' }, diff --git a/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue b/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue index 26571332..9ae84918 100644 --- a/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue +++ b/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue @@ -4,16 +4,23 @@ :class="insufficient && 'error--text'" >
- {{ model.quantity && model.quantity.value }} + {{ model.quantity.value }}
{{ model.statName || model.variableName }}
+
+ ({{ model.available }}) +
diff --git a/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue b/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue index f0eae75a..11be31fb 100644 --- a/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue +++ b/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue @@ -27,28 +27,30 @@ :color="model.itemColor" />
- - + {{ quantity }}
-
- - +
- Select item - + {{ model.itemName }} +
+
+ ({{ model.available }}) +
+ +
+ Select item
{ title: 'Print Character Sheet', }, }, - /* Not ready for prime time <3 { path: '/tabletops', name: 'tabletops', @@ -208,7 +207,6 @@ RouterFactory.configure(router => { }, beforeEnter: ensureLoggedIn, }, - */ { path: '/friends', components: { diff --git a/app/imports/client/ui/styles/cardColors.css b/app/imports/client/ui/styles/cardColors.css index 04f0f52e..2873e9a4 100644 --- a/app/imports/client/ui/styles/cardColors.css +++ b/app/imports/client/ui/styles/cardColors.css @@ -7,14 +7,22 @@ background: #151515; } +.card-background .v-tabs-items.theme--dark { + background: #151515; +} + .theme--light .card-background { background: #f6f6f6; } +.card-background .v-tabs-items.theme--light { + background: #f6f6f6; +} + .theme--dark .card-raised-background { background: #1d1d1d; } .theme--light .card-raised-background { background: #fafafa; -} +} \ No newline at end of file diff --git a/app/imports/api/tabletop/CharacterSheetDialog.vue b/app/imports/client/ui/tabletop/CharacterSheetDialog.vue similarity index 51% rename from app/imports/api/tabletop/CharacterSheetDialog.vue rename to app/imports/client/ui/tabletop/CharacterSheetDialog.vue index 93367fe8..f3b010b0 100644 --- a/app/imports/api/tabletop/CharacterSheetDialog.vue +++ b/app/imports/client/ui/tabletop/CharacterSheetDialog.vue @@ -1,41 +1,60 @@