diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3788ae9c0..16fc8651a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
## Next Release
- Cursed die support when rolling oracles ([#1026](https://github.com/ben/foundry-ironsworn/pull/1026))
+- Fix an issue with the truths dialog resulting in blank outputs ([#1027](https://github.com/ben/foundry-ironsworn/pull/1027))
## 1.24.2
diff --git a/src/module/vue/components/truth/custom-truth.vue b/src/module/vue/components/truth/custom-truth.vue
index 38a02e06a..d36090fab 100644
--- a/src/module/vue/components/truth/custom-truth.vue
+++ b/src/module/vue/components/truth/custom-truth.vue
@@ -5,20 +5,22 @@
type="radio"
:name="radioGroup"
class="nogrow"
- @change="select" />
+ @change="select"
+ />
+ @save="emitHtml"
+ />
diff --git a/src/module/vue/components/truth/truth-category.vue b/src/module/vue/components/truth/truth-category.vue
index f410257cc..4068534fb 100644
--- a/src/module/vue/components/truth/truth-category.vue
+++ b/src/module/vue/components/truth/truth-category.vue
@@ -44,6 +44,8 @@ const props = defineProps<{
je: () => IronswornJournalEntry
}>()
+const model = defineModel()
+
type NonTruthPage = IronswornJournalPage>
const truthPages = props.je()?.pageTypes.truth
@@ -57,32 +59,39 @@ const state = reactive<{
title?: string
text?: string
html?: string
+ custom?: boolean
}>({})
-function valueChange(title: string, text: string) {
+async function valueChange(title: string, text: string) {
state.title = title
state.text = text
state.html = undefined
+ model.value = await selectedValue()
}
-function customValueChange(html: string) {
+async function customValueChange(html: string) {
state.title = undefined
state.text = undefined
state.html = html
+ model.value = await selectedValue()
}
async function selectedValue() {
let html = state.html
if (!html) {
- html = `
- ${await enrichMarkdown(`**${state.title}**`)}
- ${await enrichMarkdown(state.text)}
- `
+ if (state.title) {
+ html = `
+ ${await enrichMarkdown(`**${state.title}**`)}
+ ${await enrichMarkdown(state.text)}
+ `
+ } else {
+ html = await enrichMarkdown(state.text)
+ }
}
html += nonTruthPages?.map((x) => x.text.content).join('\n\n')
return {
title: props.je()?.name,
html: html.trim(),
- valid: !!(state.title || state.html)
+ valid: true
}
}
diff --git a/src/module/vue/components/truth/truth-selectable.vue b/src/module/vue/components/truth/truth-selectable.vue
index d726cc191..58d5eaa75 100644
--- a/src/module/vue/components/truth/truth-selectable.vue
+++ b/src/module/vue/components/truth/truth-selectable.vue
@@ -73,7 +73,13 @@ const $emit = defineEmits<{
change: [string, string] // title, text
}>()
function emitValue() {
- let text = `${pageSystem.Description} ${suboption ?? ''}\n\n_${
+ // Some pages (i.e. Classic) don't have a title
+ let title = props.page.name ?? ''
+ if (title?.startsWith('truth.option')) {
+ title = ''
+ }
+
+ let text = `${pageSystem.Description} ${suboption.value ?? ''}\n\n_${
pageSystem.Quest
}_`
@@ -83,7 +89,7 @@ function emitValue() {
template.Description.replace(/{{table>.*?}}/, `> ${suboption.value}`) +
`\n\n_${pageSystem.Quest}_`
}
- $emit('change', props.page.name ?? '???', text.trim())
+ $emit('change', title, text.trim())
}
const suboptions = ref([])
@@ -104,6 +110,8 @@ async function selectAndRandomize() {
)
suboptions.value[selectedIndex]?.click()
}
+
+ emitValue()
}
defineExpose({ selectAndRandomize })
diff --git a/src/module/vue/sf-truths.vue b/src/module/vue/sf-truths.vue
index 201e171a6..8f9053de3 100644
--- a/src/module/vue/sf-truths.vue
+++ b/src/module/vue/sf-truths.vue
@@ -33,6 +33,7 @@
ref="categoryComponents"
:key="(truth.je()._id as string)"
:je="truth.je"
+ v-model="categoryModels[truth.je()._id]"
/>
@@ -57,6 +58,13 @@ const props = defineProps<{
}>()
const categoryComponents = ref<(typeof TruthCategory)[]>([])
+const categoryModels = ref<
+ Record
+>(
+ Object.fromEntries(
+ props.data.truths.map((x) => [x.je()._id, { valid: false }])
+ )
+)
function scrollToCategory(i: number) {
categoryComponents.value[i]?.scrollIntoView()
@@ -65,19 +73,17 @@ function scrollToCategory(i: number) {
const $localEmitter = inject($LocalEmitterKey)
async function saveTruths() {
// Fetch values from the category components
- const allValues = await Promise.all(
- categoryComponents.value.map((x) => x.selectedValue())
- )
- const values = allValues.filter((x) => x.valid)
+ const contentSections: string[] = []
+ for (const t of props.data.truths) {
+ const model = categoryModels.value[t.je()._id]
+ if (model.valid)
+ contentSections.push(
+ `${model.title}
+ ${model.html}`
+ )
+ }
- const content = values
- .map(
- ({ title, html }) => `
- ${title}
- ${html}
- `
- )
- .join('\n\n')
+ const content = contentSections.join('\n\n')
const title = game.i18n.localize('IRONSWORN.JOURNALENTRYPAGES.TypeTruth')
const journal = await IronswornJournalEntry.create({