From f2cea4e166467761d61dc4b8c884bf5b041245ee Mon Sep 17 00:00:00 2001 From: Aaron Lutomski Date: Sat, 30 May 2026 12:17:35 -0700 Subject: [PATCH] Style fixes --- lang/en.json | 13 +- module/applications/add-profession-dialog.js | 18 +- .../applications/rename-profession-dialog.js | 45 +++ module/macros/stat-parser-macro.js | 14 +- module/profession/catalog.js | 10 +- module/profession/validation.js | 22 +- module/roll/skill-improvement-roll.js | 22 +- module/sheets/agent-sheet.js | 40 ++- module/sheets/mixins/item-list-mixin.js | 72 ++--- .../sheets/mixins/special-training-mixin.js | 11 +- module/sheets/mixins/typed-skill-mixin.js | 264 +++++------------- scss/deltagreen/_agent-sheet.scss | 55 ++-- scss/deltagreen/_effects-tab.scss | 12 +- .../actor/partials/profession-subname.html | 15 +- .../actor/parts/motivations-tab-agent.html | 10 +- templates/dialog/rename-profession.html | 10 + templates/dialog/special-training.html | 4 +- templates/dialog/typed-skill.html | 17 ++ 18 files changed, 316 insertions(+), 338 deletions(-) create mode 100644 module/applications/rename-profession-dialog.js create mode 100644 templates/dialog/rename-profession.html create mode 100644 templates/dialog/typed-skill.html diff --git a/lang/en.json b/lang/en.json index 15c6f2d..1be7b18 100644 --- a/lang/en.json +++ b/lang/en.json @@ -230,6 +230,7 @@ "DG.Mental.AdaptedToHelplessness": "Adapted to Helplessness", "DG.Mental.Motivations": "Motivation", "DG.Mental.Disorders": "Disorder", + "DG.Gear.SelectCompendium": "Select Compendium", "DG.Gear.WeaponTypes.Firearms": "Firearms", "DG.Gear.WeaponTypes.Melee": "Melee", "DG.Gear.Weapons": "WEAPONS", @@ -342,8 +343,9 @@ "DG.Sheet.BlockHeaders.PersonalInfoCV": "PERSONAL INFORMATION / CV", "DG.Sheet.BlockHeaders.ScenarioInformation": "SCENARIO INFORMATION", "DG.Sheet.BlockHeaders.BondsRelationshipsContacts": "BONDS / RELATIONSHIPS / CONTACTS", - "DG.AgentSheet.ProfessionPlaceholder": "PROFESSION (RANK IF APPLICABLE)", - "DG.AgentSheet.OpenProfessionToEdit": "Click to edit profession", + "DG.AgentSheet.ProfessionPlaceholder": "PROFESSION (RANK)", + "DG.AgentSheet.RenameProfession.Title": "Rename Profession", + "DG.AgentSheet.RenameProfession.Tooltip": "Click to rename profession", "DG.UnnaturalSheet.HideUntrainedSkillsLabel": "Hide Untrained", "DG.UnnaturalSheet.ShortDescriptionPlaceholder": "Description of creature or creature type", "DG.UnnaturalSheet.ShowUntrainedSkillsLabel": "Show Untrained", @@ -389,14 +391,13 @@ "DG.Profession.Dialog.SkillTotalsHint": "Skills in green have been increased by your profession. Hover over a skill to see what it does or consult the Agent's Handbook for the full description.", "DG.Profession.Dialog.SkillsOptionsHeader": "Skills Options ({picks} picks)", "DG.Profession.Dialog.BonusSkillsIntro": "Select skills from the dropdowns to add 20% to their total. A skill may be selected multiple times. Unnatural cannot be selected, nor can any skill be increased above 80% at character creation.", - "DG.Profession.Dialog.BonusSkillAlreadyAtCap": "{skill} may not be increased further. Please select a different bonus skill.", - "DG.Profession.Dialog.BonusSkillWasteTooHigh": "Bonus increases to {skill} would waste {waste} skill points (at most {maxWaste} may be wasted per skill).", + "DG.Profession.Dialog.BonusSkillWasteTooHigh": "{skill} cannot be increased above 80. Select a different bonus skill.", "DG.Profession.Dialog.BondsIntro": "Bonds are the important relationships in your agent's life, such as family, friends, and other loved ones. They can provide a buffer against SAN loss, at the cost of that relationship. Initial relationship score is equal to CHA.", "DG.Profession.Dialog.BondFieldLabel": "Bond{number}", "DG.Profession.Dialog.SelectSkill": "Select a skill…", "DG.Profession.Dialog.SkillTypePlaceholder": "Type or specialization", "DG.Profession.Dialog.Submit": "Submit", - "DG.Profession.Dialog.CapWarning": "{skill} is being raised to {attempted} but is capped at 80 during agent creation. This is wasting {waste} skill points.", + "DG.Profession.Dialog.CapWarning": "{skill} is being raised to {attempted} but is capped at 80 during agent creation, wasting {waste} skill points.", "DG.Profession.Dialog.DuplicateTypedName": "Duplicate {type} ({name}) detected. Please choose unique names.", "DG.Profession.ChooseOnePlaceholder": "choose one", "DG.Profession.Dialog.ChooseOneNamesHeader": "Name Skill Specializations", @@ -419,7 +420,7 @@ "DG.ItemWindow.Profession.SkillsTab": "Skills", "DG.ItemWindow.Profession.Name": "Profession Name", "DG.ItemWindow.Profession.Bonds": "Bonds", - "DG.ItemWindow.Profession.BondsTooltip": "Number of bond slots granted when this profession is assigned to an agent (0–5).", + "DG.ItemWindow.Profession.BondsTooltip": "Number of bond slots granted when this profession is assigned to an agent (1 – 5).", "DG.ItemWindow.Profession.AutomaticSkills": "Automatic Skills", "DG.ItemWindow.Profession.OptionSkills": "Skill Options", "DG.ItemWindow.Profession.OptionPicks": "Option Picks", diff --git a/module/applications/add-profession-dialog.js b/module/applications/add-profession-dialog.js index 920e4da..7a4b8b8 100644 --- a/module/applications/add-profession-dialog.js +++ b/module/applications/add-profession-dialog.js @@ -462,16 +462,16 @@ class AddProfessionDialogController { * @returns {{ * validationMessages: string[], * capWarnings: { warning: string }[], - * atCapMessages: string[], + * wasteMessages: string[], * }} */ #getDisplayMessages(computed) { - const atCapPrefix = "bonusAtCap:"; + const wastePrefix = "bonusWaste:"; const mainErrors = computed.validationErrors.filter( - (code) => !code.startsWith(atCapPrefix), + (code) => !code.startsWith(wastePrefix), ); - const atCapErrors = computed.validationErrors.filter((code) => - code.startsWith(atCapPrefix), + const wasteErrors = computed.validationErrors.filter((code) => + code.startsWith(wastePrefix), ); return { @@ -485,7 +485,7 @@ class AddProfessionDialogController { waste: w.waste, }), })), - atCapMessages: formatProfessionValidationMessages(atCapErrors, { + wasteMessages: formatProfessionValidationMessages(wasteErrors, { optionPicks: this.optionPicks, }), }; @@ -496,7 +496,7 @@ class AddProfessionDialogController { * @returns {string} */ #buildMessagesHtml(computed) { - const { validationMessages, capWarnings, atCapMessages } = + const { validationMessages, capWarnings, wasteMessages } = this.#getDisplayMessages(computed); const toErrorHtml = (messages) => @@ -519,7 +519,9 @@ class AddProfessionDialogController { .join(""); return ( - toErrorHtml(validationMessages) + capHtml + toErrorHtml(atCapMessages) + toErrorHtml(validationMessages) + + capHtml + + toErrorHtml(wasteMessages) ); } diff --git a/module/applications/rename-profession-dialog.js b/module/applications/rename-profession-dialog.js new file mode 100644 index 0000000..ca7709d --- /dev/null +++ b/module/applications/rename-profession-dialog.js @@ -0,0 +1,45 @@ +import { BASE_TEMPLATE_PATH } from "../config/index.js"; +import { getDialogContentRoot, showDgDialog } from "./dg-dialog.js"; + +const { renderTemplate } = foundry.applications.handlebars; + +/** + * @param {Item} professionItem + * @returns {Promise} True if the name was updated. + */ +export async function showRenameProfessionDialog(professionItem) { + if (professionItem.type !== "profession") return false; + + const content = await renderTemplate( + `${BASE_TEMPLATE_PATH}/dialog/rename-profession.html`, + { name: professionItem.name }, + ); + + const result = await showDgDialog({ + modifier: "rename-profession", + content, + position: { width: 360 }, + window: { + title: game.i18n.localize("DG.AgentSheet.RenameProfession.Title"), + }, + default: "submit", + buttons: [ + { + default: true, + action: "submit", + label: game.i18n.localize("DG.Profession.Dialog.Submit"), + callback: (_event, _button, dialog) => { + const name = getDialogContentRoot(dialog) + ?.querySelector("[name='profession-rename']") + ?.value?.trim(); + return name || null; + }, + }, + ], + }); + + if (!result || result === professionItem.name) return false; + + await professionItem.update({ name: result }); + return true; +} diff --git a/module/macros/stat-parser-macro.js b/module/macros/stat-parser-macro.js index ca6787b..a2929f5 100644 --- a/module/macros/stat-parser-macro.js +++ b/module/macros/stat-parser-macro.js @@ -1,3 +1,5 @@ +import { showDgDialog } from "../applications/dg-dialog.js"; + function GetAttacksFromInput(inputText) { const attacks = []; try { @@ -661,14 +663,16 @@ async function GetUserInput() { `; - new foundry.applications.api.DialogV2({ - window: { title: "Stat Block Parser" }, + await showDgDialog({ + modifier: "stat-parser", content, + window: { title: "Stat Block Parser" }, buttons: [ { label: "PARSE", action: "roll", - callback: (event, button, dialog) => { + default: true, + callback: (_event, _button, dialog) => { const textInput = dialog.element.querySelector("[name=parse-input]")?.value; @@ -679,9 +683,9 @@ async function GetUserInput() { }, }, ], - }).render(true); + }); } export default async function ParseDeltaGreenStatBlock() { - GetUserInput(); + await GetUserInput(); } diff --git a/module/profession/catalog.js b/module/profession/catalog.js index ca9df76..2069e53 100644 --- a/module/profession/catalog.js +++ b/module/profession/catalog.js @@ -143,7 +143,7 @@ function getBonusTrackBaseValue(trackKey, baseFixed, baseTyped, defaults) { } /** - * Bonus skill slots that would waste 20+ points or raise a skill already at the creation cap. + * Bonus skill slots that would waste 20+ points over the creation cap (skill below 80). * * @param {Record} baseFixed * @param {Record} baseTyped @@ -191,7 +191,7 @@ export function collectBonusCapValidationErrors( ); const final = base + count * BONUS_SKILL_INCREMENT; const waste = Math.max(0, final - SKILL_CAP); - if (base >= SKILL_CAP || waste >= MAX_ALLOWED_BONUS_WASTE) { + if (base < SKILL_CAP && waste >= MAX_ALLOWED_BONUS_WASTE) { violatingTrackKeys.add(trackKey); } } @@ -212,11 +212,7 @@ export function collectBonusCapValidationErrors( const final = base + count * BONUS_SKILL_INCREMENT; const waste = Math.max(0, final - SKILL_CAP); - if (base >= SKILL_CAP) { - errors.push(`bonusAtCap:${i}|${trackKey}`); - } else { - errors.push(`bonusWaste:${i}|${waste}|${trackKey}`); - } + errors.push(`bonusWaste:${i}|${waste}|${trackKey}`); } return errors; diff --git a/module/profession/validation.js b/module/profession/validation.js index 57dadca..882aa35 100644 --- a/module/profession/validation.js +++ b/module/profession/validation.js @@ -1,4 +1,4 @@ -import { BONUS_SKILL_COUNT, MAX_ALLOWED_BONUS_WASTE } from "./constants.js"; +import { BONUS_SKILL_COUNT } from "./constants.js"; import { catalogIdToSkillRef, getBonusTrackLabel } from "./catalog.js"; import { getTypedGroupDisplayName, @@ -135,7 +135,7 @@ export function formatProfessionValidationMessages( /** @type {Set} */ const typedNameRequiredGroups = new Set(); /** @type {string[]} */ - const bonusAtCapTrackKeys = []; + const bonusWasteTrackKeys = []; for (const code of errors) { if (code === "optionPicks") { @@ -150,21 +150,9 @@ export function formatProfessionValidationMessages( needsBondRelationship = true; continue; } - const bonusAtCap = code.match(/^bonusAtCap:\d+\|(.+)$/); - if (bonusAtCap) { - bonusAtCapTrackKeys.push(bonusAtCap[1]); - continue; - } - const bonusWaste = code.match(/^bonusWaste:\d+\|(\d+)\|(.+)$/); if (bonusWaste) { - push( - game.i18n.format("DG.Profession.Dialog.BonusSkillWasteTooHigh", { - skill: getBonusTrackLabel(bonusWaste[2]), - waste: Number(bonusWaste[1]), - maxWaste: MAX_ALLOWED_BONUS_WASTE - 1, - }), - ); + bonusWasteTrackKeys.push(bonusWaste[2]); continue; } @@ -226,9 +214,9 @@ export function formatProfessionValidationMessages( push(game.i18n.localize("DG.Profession.Dialog.BondRelationshipRequired")); } - for (const trackKey of bonusAtCapTrackKeys) { + for (const trackKey of bonusWasteTrackKeys) { push( - game.i18n.format("DG.Profession.Dialog.BonusSkillAlreadyAtCap", { + game.i18n.format("DG.Profession.Dialog.BonusSkillWasteTooHigh", { skill: getBonusTrackLabel(trackKey), }), ); diff --git a/module/roll/skill-improvement-roll.js b/module/roll/skill-improvement-roll.js index 6d07ced..61941cd 100644 --- a/module/roll/skill-improvement-roll.js +++ b/module/roll/skill-improvement-roll.js @@ -1,5 +1,6 @@ import { createDGChatMessage } from "../chat/dg-chat-card.js"; import DG from "../config/index.js"; +import { formatProfessionSkillLabel } from "../profession/index.js"; /** * @param {"1"|"d3"|"d4"|"d4-1"} baseFormula @@ -68,23 +69,24 @@ export async function createSkillImprovementChatMessage({ failedTypedSkills, resultObj, }) { - const localizeFailedSkills = (skillsArray) => { + const localizeFailedSkills = (skillsArray, kind) => { return skillsArray.map((skill) => { const increment = resultObj[skill.key] ?? 1; const label = - skill.label ?? game.i18n.localize(`DG.Skills.${skill.key}`); - const groupLabel = skill.group - ? `${game.i18n.localize( - `DG.TypeSkills.${skill.group.replace(/\s+/g, "")}`, - )} (${label})` - : label; + kind === "typed" + ? formatProfessionSkillLabel({ + kind: "typed", + group: skill.group, + label: skill.label, + }) + : formatProfessionSkillLabel({ kind: "fixed", key: skill.key }); - return `${groupLabel}: +${increment}%`; + return `${label}: +${increment}%`; }); }; - const failedSkillNames = localizeFailedSkills(failedSkills); - const failedTypedSkillNames = localizeFailedSkills(failedTypedSkills); + const failedSkillNames = localizeFailedSkills(failedSkills, "fixed"); + const failedTypedSkillNames = localizeFailedSkills(failedTypedSkills, "typed"); const content = [...failedSkillNames, ...failedTypedSkillNames].join(", "); const label = game.i18n.format( diff --git a/module/sheets/agent-sheet.js b/module/sheets/agent-sheet.js index a46eb40..3c2bfc1 100644 --- a/module/sheets/agent-sheet.js +++ b/module/sheets/agent-sheet.js @@ -19,6 +19,7 @@ import { } from "../active-effect/runtime/stimulant-effect.js"; import { assignProfessionToAgent } from "../applications/profession-setup-flow.js"; import { showDgDialog } from "../applications/dg-dialog.js"; +import { showRenameProfessionDialog } from "../applications/rename-profession-dialog.js"; import { PROFESSION_OPTION_PICKS_KEY } from "../data/item/profession.js"; const { renderTemplate } = foundry.applications.handlebars; @@ -292,12 +293,13 @@ export default class DGAgentSheet extends AgentSheetBase { * @param {PointerEvent} _event * @param {HTMLElement} target */ - static _openProfessionItem(_event, target) { + static async _openProfessionItem(_event, target) { const itemId = target.dataset.itemId ?? target.closest("[data-item-id]")?.dataset?.itemId; const item = this.actor.items.get(itemId); - if (item?.type === "profession") item.sheet.render(true); + if (item?.type !== "profession") return; + await showRenameProfessionDialog(item); } static _clearBondDamage() { @@ -550,6 +552,18 @@ export default class DGAgentSheet extends AgentSheetBase { }); } + /** + * @param {Record} skillMap + * @returns {object[]} + */ + static _collectFailedSkills(skillMap) { + return Object.entries(skillMap) + .filter( + ([, skill]) => skill.failure && !skill.cannotBeImprovedByFailure, + ) + .map(([key, skill]) => ({ ...skill, key })); + } + /** * Runs through the whole process of improving skills, * i.e., prompting the user, rolling, and creating the chat card. @@ -559,12 +573,8 @@ export default class DGAgentSheet extends AgentSheetBase { static async _processSkillImprovements() { const { skills, typedSkills } = this.actor.system; - const failedSkills = Object.values(skills).filter( - (skill) => skill.failure && !skill.cannotBeImprovedByFailure, - ); - const failedTypedSkills = Object.values(typedSkills).filter( - (skill) => skill.failure && !skill.cannotBeImprovedByFailure, - ); + const failedSkills = DGAgentSheet._collectFailedSkills(skills); + const failedTypedSkills = DGAgentSheet._collectFailedSkills(typedSkills); if (failedSkills.length + failedTypedSkills.length === 0) { ui.notifications.warn("DG.Skills.ApplySkillImprovements.Warning", { @@ -640,14 +650,16 @@ export default class DGAgentSheet extends AgentSheetBase { failedTypedSkills, ) { const localizedFailedSkills = failedSkills.map((skill) => - game.i18n.localize(`DG.Skills.${skill.key}`), + formatProfessionSkillLabel({ kind: "fixed", key: skill.key }), ); - const localizedFailedTypedSkills = failedTypedSkills.map((skill) => { - const groupKey = `DG.TypeSkills.${skill.group.replace(/\s+/g, "")}`; - const groupLabel = game.i18n.localize(groupKey); - return `${groupLabel} (${skill.label})`; - }); + const localizedFailedTypedSkills = failedTypedSkills.map((skill) => + formatProfessionSkillLabel({ + kind: "typed", + group: skill.group, + label: skill.label, + }), + ); const failedSkillNames = [ ...localizedFailedSkills, diff --git a/module/sheets/mixins/item-list-mixin.js b/module/sheets/mixins/item-list-mixin.js index ed21374..1f06599 100644 --- a/module/sheets/mixins/item-list-mixin.js +++ b/module/sheets/mixins/item-list-mixin.js @@ -1,4 +1,4 @@ -const { DialogV2 } = foundry.applications.api; +import { showDgDialog } from "../../applications/dg-dialog.js"; /** @param {typeof foundry.applications.api.ApplicationV2} Base */ export default function ItemListMixin(Base) { @@ -189,41 +189,43 @@ export default function ItemListMixin(Base) { static _browsePack(event, target) { const { packType } = target.dataset; - switch (packType) { - case "weapon": { - new DialogV2({ - window: { title: "Select Compendium" }, - buttons: [ - { - action: "firearms", - label: game.i18n.localize("DG.Gear.WeaponTypes.Firearms"), - icon: '', - callback: () => - game.packs - .find((k) => k.collection === "deltagreen.firearms") - .render(true), - }, - { - action: "melee", - label: game.i18n.localize("DG.Gear.WeaponTypes.Melee"), - icon: '', - callback: () => - game.packs - .find( - (k) => k.collection === "deltagreen.hand-to-hand-weapons", - ) - .render(true), - }, - ], - }).render(true); - break; - } - default: - game.packs - .find((k) => k.collection === `deltagreen.${packType}`) - .render(true); - break; + if (packType === "weapon") { + void this._browseWeaponPack(); + return; } + + game.packs + .find((k) => k.collection === `deltagreen.${packType}`) + .render(true); + } + + async _browseWeaponPack() { + await showDgDialog({ + modifier: "browse-weapon-pack", + window: { + title: game.i18n.localize("DG.Gear.SelectCompendium"), + }, + buttons: [ + { + action: "firearms", + label: game.i18n.localize("DG.Gear.WeaponTypes.Firearms"), + icon: '', + callback: () => + game.packs + .find((k) => k.collection === "deltagreen.firearms") + .render(true), + }, + { + action: "melee", + label: game.i18n.localize("DG.Gear.WeaponTypes.Melee"), + icon: '', + callback: () => + game.packs + .find((k) => k.collection === "deltagreen.hand-to-hand-weapons") + .render(true), + }, + ], + }); } /** diff --git a/module/sheets/mixins/special-training-mixin.js b/module/sheets/mixins/special-training-mixin.js index 55d3f69..567d079 100644 --- a/module/sheets/mixins/special-training-mixin.js +++ b/module/sheets/mixins/special-training-mixin.js @@ -1,4 +1,4 @@ -const { DialogV2 } = foundry.applications.api; +import { showDgDialog } from "../../applications/dg-dialog.js"; /** @param {typeof foundry.applications.api.ApplicationV2} Base */ export default function SpecialTrainingMixin(Base) { @@ -23,7 +23,7 @@ export default function SpecialTrainingMixin(Base) { } break; default: - this._showSpecialTrainingDialog(actionType, id); + void this._showSpecialTrainingDialog(actionType, id); break; } } @@ -95,7 +95,8 @@ export default function SpecialTrainingMixin(Base) { `DG.SpecialTraining.Dialog.${action.capitalize()}SpecialTraining`, ); - new DialogV2({ + await showDgDialog({ + modifier: "special-training", content, window: { title: game.i18n.localize("DG.SpecialTraining.Dialog.Title"), @@ -106,7 +107,7 @@ export default function SpecialTrainingMixin(Base) { default: true, action: "confirm", label: buttonLabel, - callback: (event, button, dialog) => { + callback: (_event, _button, dialog) => { const specialTrainingLabel = dialog.element.querySelector( "[name='special-training-label']", )?.value; @@ -127,7 +128,7 @@ export default function SpecialTrainingMixin(Base) { }, }, ], - }).render(true); + }); } _createSpecialTraining(label, attribute) { diff --git a/module/sheets/mixins/typed-skill-mixin.js b/module/sheets/mixins/typed-skill-mixin.js index b3a49a5..1204206 100644 --- a/module/sheets/mixins/typed-skill-mixin.js +++ b/module/sheets/mixins/typed-skill-mixin.js @@ -1,4 +1,23 @@ -const { DialogV2 } = foundry.applications.api; +import { showDgDialog } from "../../applications/dg-dialog.js"; +import { BASE_TEMPLATE_PATH } from "../../config/index.js"; +import { + TYPED_GROUP_I18N, + TYPED_SKILL_TEMPLATE_GROUPS, +} from "../../profession/constants.js"; + +const { renderTemplate } = foundry.applications.handlebars; + +/** + * @param {string} [selectedGroup] + * @returns {{ value: string, label: string, selected: boolean }[]} + */ +function buildTypedSkillGroupOptions(selectedGroup) { + return TYPED_SKILL_TEMPLATE_GROUPS.map((value) => ({ + value, + label: game.i18n.localize(TYPED_GROUP_I18N[value]), + selected: value === selectedGroup, + })); +} /** @param {typeof foundry.applications.api.ApplicationV2} Base */ export default function TypedSkillMixin(Base) { @@ -7,10 +26,13 @@ export default function TypedSkillMixin(Base) { const { actionType, typedskill } = target.dataset; switch (actionType) { case "create": - this._showNewTypeSkillDialog(); + void this._showTypedSkillDialog({ mode: "create" }); break; case "edit": - this._showNewEditTypeSkillDialog(typedskill); + void this._showTypedSkillDialog({ + mode: "edit", + targetSkill: typedskill, + }); break; case "delete": this.actor.update({ [`system.typedSkills.-=${typedskill}`]: null }); @@ -20,215 +42,61 @@ export default function TypedSkillMixin(Base) { } } - _showNewEditTypeSkillDialog(targetSkill) { - const { typedSkills } = this.actor.system; - const currentLabel = typedSkills[targetSkill].label; - const currentGroup = typedSkills[targetSkill].group; + /** + * @param {{ mode: "create" | "edit", targetSkill?: string }} options + */ + async _showTypedSkillDialog({ mode, targetSkill }) { + const isEdit = mode === "edit"; + const typedSkills = this.actor.system.typedSkills; + const currentLabel = isEdit ? typedSkills[targetSkill].label : ""; + const currentGroup = isEdit + ? typedSkills[targetSkill].group + : TYPED_SKILL_TEMPLATE_GROUPS[0]; - let htmlContent = `
`; - htmlContent += ` `; - htmlContent += ` `; - htmlContent += `
`; - - htmlContent += `
`; - htmlContent += ` `; - htmlContent += ` `; - htmlContent += `
`; - - new DialogV2({ - content: htmlContent, - window: { - title: - game.i18n.translations.DG?.Skills?.EditTypedOrCustomSkill ?? - "Edit Typed or Custom Skill", + const content = await renderTemplate( + `${BASE_TEMPLATE_PATH}/dialog/typed-skill.html`, + { + groups: buildTypedSkillGroupOptions(currentGroup), + label: currentLabel, }, + ); + + const titleKey = isEdit + ? "DG.Skills.EditTypedOrCustomSkill" + : "DG.Skills.AddTypedOrCustomSkill"; + const buttonKey = isEdit ? "DG.Skills.EditSkill" : "DG.Skills.AddSkill"; + + await showDgDialog({ + modifier: "typed-skill", + content, + position: { width: 320 }, + window: { title: game.i18n.localize(titleKey) }, + default: "submit", buttons: [ { default: true, - action: "add", - label: game.i18n.translations.DG?.Skills?.EditSkill ?? "Edit Skill", - callback: (event, button, dialog) => { + action: "submit", + label: game.i18n.localize(buttonKey), + callback: (_event, _button, dialog) => { const newTypeSkillLabel = dialog.element.querySelector( "[name='new-type-skill-label']", )?.value; const newTypeSkillGroup = dialog.element.querySelector( "[name='new-type-skill-group']", )?.value; - this._updateTypedSkill( - targetSkill, - newTypeSkillLabel, - newTypeSkillGroup, - ); + if (isEdit) { + this._updateTypedSkill( + targetSkill, + newTypeSkillLabel, + newTypeSkillGroup, + ); + } else { + this._addNewTypedSkill(newTypeSkillLabel, newTypeSkillGroup); + } }, }, ], - }).render(true); - } - - _showNewTypeSkillDialog() { - let htmlContent = ""; - - htmlContent += `
`; - htmlContent += ` `; - htmlContent += ` `; - htmlContent += `
`; - - htmlContent += `
`; - htmlContent += ` `; - htmlContent += ` `; - htmlContent += `
`; - - new DialogV2({ - content: htmlContent, - window: { - title: - game.i18n.translations.DG?.Skills?.AddTypedOrCustomSkill ?? - "Add Typed or Custom Skill", - }, - default: "add", - buttons: [ - { - default: true, - action: "add", - label: game.i18n.translations.DG?.Skills?.AddSkill ?? "Add Skill", - callback: (event, button, dialog) => { - const newTypeSkillLabel = dialog.element.querySelector( - "[name='new-type-skill-label']", - )?.value; - const newTypeSkillGroup = dialog.element.querySelector( - "[name='new-type-skill-group']", - )?.value; - this._addNewTypedSkill(newTypeSkillLabel, newTypeSkillGroup); - }, - }, - ], - }).render(true); + }); } _addNewTypedSkill(newSkillLabel, newSkillGroup) { diff --git a/scss/deltagreen/_agent-sheet.scss b/scss/deltagreen/_agent-sheet.scss index c7b007a..9654e15 100644 --- a/scss/deltagreen/_agent-sheet.scss +++ b/scss/deltagreen/_agent-sheet.scss @@ -17,15 +17,26 @@ padding: 3px; } - .left-bar .profession-subname-link { - display: block; - box-sizing: border-box; - padding: 1px 2px; - line-height: var(--line-height-18, 1.125rem); - text-decoration: none; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + /* DG global form inputs use height: unset; restore Foundry sizing in the header. */ + .left-bar .header-name-fields > input { + height: var(--input-height); + line-height: var(--input-height); + } + + .left-bar .header-name-fields > input + input { + margin-top: 2px; + } + + .left-bar .header-name-fields > input.profession-subname-display[readonly] { + cursor: pointer; + --input-background-color: rgba(0, 0, 0, 0.1); + --input-border-color: var(--color-dark-6); + --input-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + --input-text-color: inherit; + + &:hover { + --input-background-color: rgba(0, 0, 0, 0.12); + } } .stats-wrapper { @@ -244,18 +255,18 @@ .resources .resource-inner-grid-3col input { box-sizing: border-box; - width: 1.5rem; - height: 1.5rem; + width: 1.75rem; + height: 1.75rem; padding: 1px; - line-height: calc(1.5rem - 4px); + line-height: calc(1.75rem - 4px); } .resources .resource-inner-grid-3col .max-resource-value { box-sizing: border-box; - width: 1.5rem; - height: 1.5rem; - min-width: 1.5rem; - min-height: 1.5rem; + width: 1.7rem; + height: 1.75rem; + min-width: 1.75rem; + min-height: 1.75rem; } .breaking-point-inline { @@ -807,8 +818,16 @@ .tab.motivations .items-list .item-header .acute-episode-col, .tab.motivations .items-list .item .acute-episode-col { - flex: 0 0 5.5rem; - text-align: center; + flex: 0 0 7.75rem; + min-width: 7.75rem; + display: flex; + justify-content: center; + align-items: center; + white-space: nowrap; + + input[type="checkbox"] { + margin: 0; + } } /* Equipment tab */ diff --git a/scss/deltagreen/_effects-tab.scss b/scss/deltagreen/_effects-tab.scss index d604178..5456a93 100644 --- a/scss/deltagreen/_effects-tab.scss +++ b/scss/deltagreen/_effects-tab.scss @@ -93,8 +93,16 @@ } .deltagreen .motivations .acute-episode-col { - flex: 0 0 5.5rem; - text-align: center; + flex: 0 0 7.75rem; + min-width: 7.75rem; + display: flex; + justify-content: center; + align-items: center; + white-space: nowrap; + + input[type="checkbox"] { + margin: 0; + } } .deltagreen .motivations li.acute-episode-active { diff --git a/templates/actor/partials/profession-subname.html b/templates/actor/partials/profession-subname.html index 0f0baad..ee7b340 100644 --- a/templates/actor/partials/profession-subname.html +++ b/templates/actor/partials/profession-subname.html @@ -1,12 +1,13 @@ {{#if professionItem}} - - {{professionItem.name}} - + {{else}} -
{{localize 'DG.Mental.Motivations'}}
-
{{localize 'DG.ItemWindow.Motivations.AcuteEpisode'}}
{{localize 'DG.Mental.Disorders'}}
+
{{localize 'DG.ItemWindow.Motivations.AcuteEpisode'}}