Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 76 additions & 24 deletions src/components/sources/FactTable.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import { ref, inject } from "vue";
import { ref, inject, computed } from "vue";
import { storeToRefs } from "pinia";
import { toast } from "bulma-toast";

Expand All @@ -17,6 +17,31 @@ let factIndexToEdit = ref(-1);
let showAbilitySelection = ref(false);
let showAddFromAdversary = ref(false);

// Track which trait groups are expanded (collapsed by default if many values)
let expandedTraits = ref({});

// Group facts by trait name for display
const groupedFacts = computed(() => {
const groups = {};
if (!selectedSource.value || !selectedSource.value.facts) return groups;
selectedSource.value.facts.forEach((fact, index) => {
const trait = fact.trait || "---";
if (!groups[trait]) {
groups[trait] = [];
}
groups[trait].push({ ...fact, _index: index });
});
return groups;
});

function toggleTrait(trait) {
expandedTraits.value[trait] = !expandedTraits.value[trait];
}

function isTraitExpanded(trait) {
return expandedTraits.value[trait] !== false;
}

function addFact() {
selectedSource.value.facts.push({
trait: "",
Expand All @@ -26,6 +51,16 @@ function addFact() {
factIndexToEdit.value = selectedSource.value.facts.length - 1;
}

function addValueToTrait(traitName) {
selectedSource.value.facts.push({
trait: traitName,
value: "",
score: 0,
});
factIndexToEdit.value = selectedSource.value.facts.length - 1;
expandedTraits.value[traitName] = true;
}

function removeFact(factIndex) {
selectedSource.value.facts.splice(factIndex, 1);
saveFacts();
Expand Down Expand Up @@ -124,30 +159,47 @@ table.table.is-striped.is-fullwidth
th Score
th
tbody
tr(v-for="(fact, index) of selectedSource.facts")
td
input.input(v-if="factIndexToEdit === index" v-model="fact.trait" placeholder="Fact trait")
div.is-flex.is-flex-direction-row(v-else)
span {{ fact.trait || "---" }}
#fact-source-icon.tag.ml-2(v-if="fact.origin_type" :class="getFactOriginColor(fact.origin_type)" v-tooltip="`Origin: ${fact.origin_type.toLowerCase()}`") {{ getFactOriginShort(fact.origin_type) }}
td
input.input(v-if="factIndexToEdit === index" v-model="fact.value" placeholder="Fact value")
span(v-else) {{ fact.value || "---" }}
td
input.input(v-if="factIndexToEdit === index" v-model="fact.score" placeholder="Fact score")
span(v-else) {{ fact.score }}
td
.buttons
button.button.is-primary(
v-if="factIndexToEdit === index" @click="saveFacts()")
span.icon
font-awesome-icon(icon="fa-save")
button.button(v-else @click="factIndexToEdit = index")
span.icon
font-awesome-icon(icon="fa-pencil-alt")
button.button.is-danger.is-outlined(@click="removeFact(index)")
template(v-for="(facts, trait) in groupedFacts" :key="trait")
//- Trait group header row
tr.has-background-dark
td(colspan="3")
.is-flex.is-align-items-center
button.button.is-small.is-ghost.mr-2(@click="toggleTrait(trait)" style="min-width: 1.5em")
span.icon
font-awesome-icon(:icon="isTraitExpanded(trait) ? 'fa-chevron-down' : 'fa-chevron-right'")
strong {{ trait }}
span.tag.ml-2.is-dark {{ facts.length }} value{{ facts.length !== 1 ? 's' : '' }}
td
button.button.is-small(@click="addValueToTrait(trait)" v-tooltip="`Add a new value for '${trait}'`")
span.icon
font-awesome-icon(icon="fa-trash")
font-awesome-icon(icon="fas fa-plus")
span Add Value
//- Individual fact rows within the group
template(v-if="isTraitExpanded(trait)")
tr(v-for="fact in facts" :key="fact._index")
td
input.input(v-if="factIndexToEdit === fact._index" v-model="fact.trait" placeholder="Fact trait")
div.is-flex.is-flex-direction-row(v-else)
span {{ fact.trait || "---" }}
#fact-source-icon.tag.ml-2(v-if="fact.origin_type" :class="getFactOriginColor(fact.origin_type)" v-tooltip="`Origin: ${fact.origin_type.toLowerCase()}`") {{ getFactOriginShort(fact.origin_type) }}
td
input.input(v-if="factIndexToEdit === fact._index" v-model="fact.value" placeholder="Fact value")
span(v-else) {{ fact.value || "---" }}
td
input.input(v-if="factIndexToEdit === fact._index" v-model="fact.score" placeholder="Fact score")
span(v-else) {{ fact.score }}
td
.buttons
button.button.is-primary(
v-if="factIndexToEdit === fact._index" @click="saveFacts()")
span.icon
font-awesome-icon(icon="fa-save")
button.button(v-else @click="factIndexToEdit = fact._index")
span.icon
font-awesome-icon(icon="fa-pencil-alt")
button.button.is-danger.is-outlined(@click="removeFact(fact._index)")
span.icon
font-awesome-icon(icon="fa-trash")

//- Modals
AbilitySelection(:active="showAbilitySelection" @select="addFromAbility" @close="showAbilitySelection = false" :canCreate="false")
Expand Down
Loading