diff --git a/daggerheart.mjs b/daggerheart.mjs index 9b767009..2b25ce77 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -4,7 +4,7 @@ import * as models from './module/data/_module.mjs'; import * as documents from './module/documents/_module.mjs'; import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs'; import DhCombatTracker from './module/ui/combatTracker.mjs'; -import { GMUpdateEvent, handleSocketEvent, socketEvent } from './module/helpers/socket.mjs'; +import { handleSocketEvent, registerSocketHooks } from './module/helpers/socket.mjs'; import { registerDHSettings } from './module/applications/settings.mjs'; import DhpChatLog from './module/ui/chatLog.mjs'; import DhpRuler from './module/ui/ruler.mjs'; @@ -13,12 +13,13 @@ import { DhDualityRollEnricher, DhTemplateEnricher } from './module/enrichers/_m import { getCommandTarget, rollCommandToJSON, setDiceSoNiceForDualityRoll } from './module/helpers/utils.mjs'; import { abilities } from './module/config/actorConfig.mjs'; import Resources from './module/applications/resources.mjs'; -import { NarrativeCountdowns, registerCountdownHooks } from './module/applications/countdowns.mjs'; +import { NarrativeCountdowns, registerCountdownApplicationHooks } from './module/applications/countdowns.mjs'; import DHDualityRoll from './module/data/chat-message/dualityRoll.mjs'; import { DualityRollColor } from './module/data/settings/Appearance.mjs'; import { DhMeasuredTemplate } from './module/placeables/_module.mjs'; import { renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs'; import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs'; +import { registerCountdownHooks } from './module/data/countdowns.mjs'; globalThis.SYSTEM = SYSTEM; @@ -135,34 +136,12 @@ Hooks.on('ready', () => { ); registerCountdownHooks(); + registerSocketHooks(); + registerCountdownApplicationHooks(); }); Hooks.once('dicesoniceready', () => {}); -Hooks.on(socketEvent.GMUpdate, async (action, uuid, update) => { - if (game.user.isGM) { - const document = uuid ? await fromUuid(uuid) : null; - switch (action) { - case GMUpdateEvent.UpdateDocument: - if (document && update) { - await document.update(update); - } - break; - case GMUpdateEvent.UpdateFear: - if (game.user.isGM) { - await game.settings.set( - SYSTEM.id, - SYSTEM.SETTINGS.gameSettings.Resources.Fear, - Math.max(Math.min(update, 6), 0) - ); - Hooks.callAll(socketEvent.DhpFearUpdate); - await game.socket.emit(`system.${SYSTEM.id}`, { action: socketEvent.DhpFearUpdate }); - } - break; - } - } -}); - Hooks.on('renderChatMessageHTML', (_, element) => { element .querySelectorAll('.duality-roll-button') diff --git a/lang/en.json b/lang/en.json index f10a00c9..e4ad9cd5 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1056,12 +1056,20 @@ "AddCountdown": "Add Countdown", "RemoveCountdownTitle": "Remove Countdown", "RemoveCountdownText": "Are you sure you want to remove the countdown: {name}?", + "OpenOwnership": "Edit Player Ownership", "Title": "{type} Countdowns", "Types": { "narrative": "Narrative", "encounter": "Encounter" + }, + "Notifications": { + "LimitedOwnershipMaximise": "You don't have permission to enter edit view" } }, + "OwnershipSelection": { + "Title": "Ownership Selection - {name}", + "Default": "Default Ownership" + }, "Sheets": { "PC": { "Name": "Name", diff --git a/module/applications/countdowns.mjs b/module/applications/countdowns.mjs index 6969e617..354541fe 100644 --- a/module/applications/countdowns.mjs +++ b/module/applications/countdowns.mjs @@ -1,4 +1,6 @@ import { countdownTypes } from '../config/generalConfig.mjs'; +import { GMUpdateEvent, RefreshType, socketEvent } from '../helpers/socket.mjs'; +import OwnershipSelection from './ownershipSelection.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; @@ -28,7 +30,9 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { actions: { addCountdown: this.addCountdown, removeCountdown: this.removeCountdown, - editImage: this.onEditImage + editImage: this.onEditImage, + openOwnership: this.openOwnership, + openCountdownOwnership: this.openCountdownOwnership }, form: { handler: this.updateData, submitOnChange: true } }; @@ -60,8 +64,23 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { const context = await super._prepareContext(_options); const countdownData = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath]; + context.isGM = game.user.isGM; context.base = this.basePath; - context.source = countdownData.toObject(); + + context.canCreate = countdownData.playerOwnership[game.user.id].value === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER; + context.source = { + ...countdownData, + countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => { + const countdown = countdownData.countdowns[key]; + + const ownershipValue = countdown.playerOwnership[game.user.id].value; + if (ownershipValue > CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) { + acc[key] = { ...countdown, canEdit: ownershipValue === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER }; + } + + return acc; + }, {}) + }; context.systemFields = countdownData.schema.fields; context.countdownFields = context.systemFields.countdowns.element.fields; context.minimized = this.minimized || _options.isFirstRender; @@ -75,8 +94,20 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns).toObject(), data ); - await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, newSetting); - this.render(); + + if (game.user.isGM) { + await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, newSetting); + this.render(); + } else { + await game.socket.emit(`system.${SYSTEM.id}`, { + action: socketEvent.GMUpdate, + data: { + action: GMUpdateEvent.UpdateSetting, + uuid: SYSTEM.SETTINGS.gameSettings.Countdowns, + update: newSetting + } + }); + } } async minimize() { @@ -88,6 +119,12 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { async maximize() { if (this.minimized) { + const settings = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath]; + if (settings.playerOwnership[game.user.id].value <= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED) { + ui.notifications.info(game.i18n.localize('DAGGERHEART.Countdown.Notifications.LimitedOwnership')); + return; + } + this.element.querySelector('.expanded-view').classList.toggle('hidden'); this.element.querySelector('.minimized-view').classList.toggle('hidden'); } @@ -95,6 +132,31 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { await super.maximize(); } + async updateSetting(update) { + if (game.user.isGM) { + await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, update); + await game.socket.emit(`system.${SYSTEM.id}`, { + action: socketEvent.Refresh, + data: { + refreshType: RefreshType.Countdown, + application: `${this.basePath}-countdowns` + } + }); + + this.render(); + } else { + await game.socket.emit(`system.${SYSTEM.id}`, { + action: socketEvent.GMUpdate, + data: { + action: GMUpdateEvent.UpdateSetting, + uuid: SYSTEM.SETTINGS.gameSettings.Countdowns, + update: update, + refresh: { refreshType: RefreshType.Countdown, application: `${this.basePath}-countdowns` } + } + }); + } + } + static onEditImage(_, target) { const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath]; const current = setting.countdowns[target.dataset.countdown].img; @@ -114,13 +176,51 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { [`${this.basePath}.countdowns.${countdown}.img`]: path }); - await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, setting); - this.render(); + await this.updateSetting(setting); + } + + static openOwnership(_, target) { + new Promise((resolve, reject) => { + const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath]; + const ownership = { default: setting.ownership.default, players: setting.playerOwnership }; + new OwnershipSelection(resolve, reject, this.title, ownership).render(true); + }).then(async ownership => { + const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns); + await setting.updateSource({ + [`${this.basePath}.ownership`]: ownership + }); + + await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, setting.toObject()); + this.render(); + }); + } + + static openCountdownOwnership(_, target) { + const countdownId = target.dataset.countdown; + new Promise((resolve, reject) => { + const countdown = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath] + .countdowns[countdownId]; + const ownership = { default: countdown.ownership.default, players: countdown.playerOwnership }; + new OwnershipSelection(resolve, reject, countdown.name, ownership).render(true); + }).then(async ownership => { + const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns); + await setting.updateSource({ + [`${this.basePath}.countdowns.${countdownId}.ownership`]: ownership + }); + + await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, setting); + this.render(); + }); } async updateCountdownValue(event, increase) { const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns); const countdown = countdownSetting[this.basePath].countdowns[event.currentTarget.dataset.countdown]; + + if (countdown.playerOwnership[game.user.id] < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) { + return; + } + const currentValue = countdown.progress.current; if (increase && currentValue === countdown.progress.max) return; @@ -132,20 +232,25 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { : currentValue - 1 }); - await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject()); - this.render(); + await this.updateSetting(countdownSetting.toObject()); } static async addCountdown() { const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns); await countdownSetting.updateSource({ [`${this.basePath}.countdowns.${foundry.utils.randomID()}`]: { - name: game.i18n.localize('DAGGERHEART.Countdown.NewCountdown') + name: game.i18n.localize('DAGGERHEART.Countdown.NewCountdown'), + ownership: game.user.isGM + ? {} + : { + players: { + [game.user.id]: { type: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER } + } + } } }); - await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject()); - this.render(); + await this.updateSetting(countdownSetting.toObject()); } static async removeCountdown(_, target) { @@ -162,8 +267,7 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { await countdownSetting.updateSource({ [`${this.basePath}.countdowns.-=${target.dataset.countdown}`]: null }); - await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject()); - this.render(); + await this.updateSetting(countdownSetting.toObject()); } async open() { @@ -197,7 +301,7 @@ export class EncounterCountdowns extends Countdowns { }; } -export const registerCountdownHooks = () => { +export const registerCountdownApplicationHooks = () => { const updateCountdowns = async shouldIncrease => { if (game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation).countdowns) { const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns); diff --git a/module/applications/ownershipSelection.mjs b/module/applications/ownershipSelection.mjs new file mode 100644 index 00000000..b8de22f8 --- /dev/null +++ b/module/applications/ownershipSelection.mjs @@ -0,0 +1,72 @@ +const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; + +export default class OwnershipSelection extends HandlebarsApplicationMixin(ApplicationV2) { + constructor(resolve, reject, name, ownership) { + super({}); + + this.resolve = resolve; + this.reject = reject; + this.name = name; + this.ownership = ownership; + } + + static DEFAULT_OPTIONS = { + tag: 'form', + classes: ['daggerheart', 'views', 'ownership-selection'], + position: { + width: 600, + height: 'auto' + }, + form: { handler: this.updateData } + }; + + static PARTS = { + selection: { + template: 'systems/daggerheart/templates/views/ownershipSelection.hbs' + } + }; + + get title() { + return game.i18n.format('DAGGERHEART.OwnershipSelection.Title', { name: this.name }); + } + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + context.ownershipOptions = Object.keys(CONST.DOCUMENT_OWNERSHIP_LEVELS).map(level => ({ + value: CONST.DOCUMENT_OWNERSHIP_LEVELS[level], + label: game.i18n.localize(`OWNERSHIP.${level}`) + })); + context.ownership = { + default: this.ownership.default, + players: Object.keys(this.ownership.players).reduce((acc, x) => { + const user = game.users.get(x); + if (!user.isGM) { + acc[x] = { + img: user.character?.img, + name: user.name, + ownership: this.ownership.players[x].value + }; + } + + return acc; + }, {}) + }; + + return context; + } + + static async updateData(event, _, formData) { + const { ownership } = foundry.utils.expandObject(formData.object); + + this.resolve(ownership); + this.close(true); + } + + async close(fromSave) { + if (!fromSave) { + this.reject(); + } + + await super.close(); + } +} diff --git a/module/data/countdowns.mjs b/module/data/countdowns.mjs index b163e2f9..fec2b790 100644 --- a/module/data/countdowns.mjs +++ b/module/data/countdowns.mjs @@ -1,4 +1,5 @@ import { countdownTypes } from '../config/generalConfig.mjs'; +import { RefreshType, socketEvent } from '../helpers/socket.mjs'; export default class DhCountdowns extends foundry.abstract.DataModel { static defineSchema() { @@ -19,9 +20,40 @@ class DhCountdownData extends foundry.abstract.DataModel { static defineSchema() { const fields = foundry.data.fields; return { - countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCountdown)) + countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCountdown)), + ownership: new fields.SchemaField({ + default: new fields.NumberField({ + required: true, + choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS), + initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE + }), + players: new fields.TypedObjectField( + new fields.SchemaField({ + type: new fields.NumberField({ + required: true, + choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS), + initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT + }) + }) + ) + }) }; } + + get playerOwnership() { + return Array.from(game.users).reduce((acc, user) => { + acc[user.id] = { + value: user.isGM + ? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER + : this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1 + ? this.ownership.players[user.id].type + : this.ownership.default, + isGM: user.isGM + }; + + return acc; + }, {}); + } } class DhCountdown extends foundry.abstract.DataModel { @@ -37,6 +69,22 @@ class DhCountdown extends foundry.abstract.DataModel { base64: false, initial: 'icons/magic/time/hourglass-yellow-green.webp' }), + ownership: new fields.SchemaField({ + default: new fields.NumberField({ + required: true, + choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS), + initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE + }), + players: new fields.TypedObjectField( + new fields.SchemaField({ + type: new fields.NumberField({ + required: true, + choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS), + initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT + }) + }) + ) + }), progress: new fields.SchemaField({ current: new fields.NumberField({ required: true, @@ -64,4 +112,28 @@ class DhCountdown extends foundry.abstract.DataModel { }) }; } + + get playerOwnership() { + return Array.from(game.users).reduce((acc, user) => { + acc[user.id] = { + value: user.isGM + ? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER + : this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1 + ? this.ownership.players[user.id].type + : this.ownership.default, + isGM: user.isGM + }; + + return acc; + }, {}); + } } + +export const registerCountdownHooks = () => { + Hooks.on(socketEvent.Refresh, ({ refreshType, application }) => { + if (refreshType === RefreshType.Countdown) { + foundry.applications.instances.get(application)?.render(); + return false; + } + }); +}; diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index 840b831c..61eec6c4 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -5,7 +5,7 @@ import BaseDataItem from './base.mjs'; const featureSchema = () => { return new foundry.data.fields.SchemaField({ name: new foundry.data.fields.StringField({ required: true }), - effects: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), + effects: new ForeignDocumentUUIDArrayField({ type: 'ActiveEffect', required: false }), actions: new foundry.data.fields.ArrayField(new ActionField()) }); }; diff --git a/module/helpers/socket.mjs b/module/helpers/socket.mjs index fd768d34..6cd041aa 100644 --- a/module/helpers/socket.mjs +++ b/module/helpers/socket.mjs @@ -1,20 +1,68 @@ export function handleSocketEvent({ action = null, data = {} } = {}) { switch (action) { case socketEvent.GMUpdate: - Hooks.callAll(socketEvent.GMUpdate, data.action, data.uuid, data.update); + Hooks.callAll(socketEvent.GMUpdate, data); break; case socketEvent.DhpFearUpdate: Hooks.callAll(socketEvent.DhpFearUpdate); break; + case socketEvent.Refresh: + Hooks.call(socketEvent.Refresh, data); + break; } } export const socketEvent = { - GMUpdate: 'DhpGMUpdate', - DhpFearUpdate: 'DhpFearUpdate' + GMUpdate: 'DhGMUpdate', + Refresh: 'DhRefresh', + DhpFearUpdate: 'DhFearUpdate' }; export const GMUpdateEvent = { - UpdateDocument: 'DhpGMUpdateDocument', - UpdateFear: 'DhpUpdateFear' + UpdateDocument: 'DhGMUpdateDocument', + UpdateSetting: 'DhGMUpdateSetting', + UpdateFear: 'DhGMUpdateFear' +}; + +export const RefreshType = { + Countdown: 'DhCoundownRefresh' +}; + +export const registerSocketHooks = () => { + Hooks.on(socketEvent.GMUpdate, async data => { + if (game.user.isGM) { + const document = data.uuid ? await fromUuid(data.uuid) : null; + switch (data.action) { + case GMUpdateEvent.UpdateDocument: + if (document && data.update) { + await document.update(data.update); + } + break; + case GMUpdateEvent.UpdateSetting: + if (game.user.isGM) { + await game.settings.set(SYSTEM.id, data.uuid, data.update); + } + break; + case GMUpdateEvent.UpdateFear: + if (game.user.isGM) { + await game.settings.set( + SYSTEM.id, + SYSTEM.SETTINGS.gameSettings.Resources.Fear, + Math.max(Math.min(data.update, 6), 0) + ); + Hooks.callAll(socketEvent.DhpFearUpdate); + await game.socket.emit(`system.${SYSTEM.id}`, { action: socketEvent.DhpFearUpdate }); + } + break; + } + + if (data.refresh) { + await game.socket.emit(`system.${SYSTEM.id}`, { + action: socketEvent.Refresh, + data: data.refresh + }); + Hooks.call(socketEvent.Refresh, data.refresh); + } + } + }); }; diff --git a/styles/countdown.less b/styles/countdown.less index 3f1c7c2e..ef5279aa 100644 --- a/styles/countdown.less +++ b/styles/countdown.less @@ -90,6 +90,14 @@ .countdown-fieldset { width: 340px; height: min-content; + position: relative; + + .ownership-button { + position: absolute; + top: 8px; + right: 8px; + font-size: 18px; + } .countdown-container { display: flex; @@ -100,6 +108,10 @@ width: 150px; height: 150px; cursor: pointer; + + &.disabled { + cursor: initial; + } } .countdown-inner-container { diff --git a/styles/daggerheart.css b/styles/daggerheart.css index 5b166253..1adab278 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -3077,6 +3077,24 @@ div.daggerheart.views.multiclass { .daggerheart.levelup .levelup-footer { display: flex; } +.daggerheart.views.ownership-selection .ownership-outer-container { + display: flex; + flex-direction: column; + gap: 8px; +} +.daggerheart.views.ownership-selection .ownership-outer-container .ownership-container { + display: flex; + border: 2px solid light-dark(#18162e, #f3c267); + border-radius: 6px; + padding: 0 4px 0 0; + align-items: center; + gap: 8px; +} +.daggerheart.views.ownership-selection .ownership-outer-container .ownership-container img { + height: 40px; + width: 40px; + border-radius: 6px 0 0 6px; +} :root { --shadow-text-stroke: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000; --fear-animation: background 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease, opacity 0.3s ease; @@ -3268,6 +3286,13 @@ div.daggerheart.views.multiclass { .daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset { width: 340px; height: min-content; + position: relative; +} +.daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .ownership-button { + position: absolute; + top: 8px; + right: 8px; + font-size: 18px; } .daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .countdown-container { display: flex; @@ -3279,6 +3304,9 @@ div.daggerheart.views.multiclass { height: 150px; cursor: pointer; } +.daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .countdown-container img.disabled { + cursor: initial; +} .daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .countdown-container .countdown-inner-container { display: flex; flex-direction: column; diff --git a/styles/daggerheart.less b/styles/daggerheart.less index cbf79843..d5e7f76a 100755 --- a/styles/daggerheart.less +++ b/styles/daggerheart.less @@ -10,6 +10,7 @@ @import './dialog.less'; @import './characterCreation.less'; @import './levelup.less'; +@import './ownershipSelection.less'; @import '../node_modules/@yaireo/tagify/dist/tagify.css'; @import './resources.less'; @import './countdown.less'; diff --git a/styles/ownershipSelection.less b/styles/ownershipSelection.less new file mode 100644 index 00000000..f5093bee --- /dev/null +++ b/styles/ownershipSelection.less @@ -0,0 +1,22 @@ +.daggerheart.views.ownership-selection { + .ownership-outer-container { + display: flex; + flex-direction: column; + gap: 8px; + + .ownership-container { + display: flex; + border: 2px solid light-dark(@dark-blue, @golden); + border-radius: 6px; + padding: 0 4px 0 0; + align-items: center; + gap: 8px; + + img { + height: 40px; + width: 40px; + border-radius: 6px 0 0 6px; + } + } + } +} diff --git a/templates/views/countdowns.hbs b/templates/views/countdowns.hbs index 0e287711..97f674ee 100644 --- a/templates/views/countdowns.hbs +++ b/templates/views/countdowns.hbs @@ -1,21 +1,29 @@
-
+
+ {{#if canCreate}}{{/if}} + {{#if isGM}}{{/if}} +
{{#each source.countdowns}}
- {{this.name}} + + {{this.name}} + {{#if this.canEdit}}{{/if}} + {{#if @root.isGM}}{{/if}} + +
- +
- {{formGroup @root.countdownFields.name name=(concat @root.base ".countdowns." @key ".name") value=this.name localize=true}} + {{formGroup @root.countdownFields.name name=(concat @root.base ".countdowns." @key ".name") value=this.name localize=true disabled=(not this.canEdit)}}
- {{formGroup @root.countdownFields.progress.fields.current name=(concat @root.base ".countdowns." @key ".progress.current") value=this.progress.current localize=true}} - {{formGroup @root.countdownFields.progress.fields.max name=(concat @root.base ".countdowns." @key ".progress.max") value=this.progress.max localize=true}} + {{formGroup @root.countdownFields.progress.fields.current name=(concat @root.base ".countdowns." @key ".progress.current") value=this.progress.current localize=true disabled=(not this.canEdit)}} + {{formGroup @root.countdownFields.progress.fields.max name=(concat @root.base ".countdowns." @key ".progress.max") value=this.progress.max localize=true disabled=(not this.canEdit)}}
- {{formGroup @root.countdownFields.progress.fields.type.fields.value name=(concat @root.base ".countdowns." @key ".progress.type.value") value=this.progress.type.value localize=true localize=true}} + {{formGroup @root.countdownFields.progress.fields.type.fields.value name=(concat @root.base ".countdowns." @key ".progress.type.value") value=this.progress.type.value localize=true localize=true disabled=(not this.canEdit)}}
@@ -24,7 +32,7 @@