Skip to content
Merged
Show file tree
Hide file tree
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
24 changes: 21 additions & 3 deletions custom_components/taskmate/www/taskmate-bounty-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ class TaskMateBountyCard extends LitElement {
return c ? c.name : "?";
}

/**
* Who an open-to-everyone bounty shows as able to claim it (#1071). That
* avatar row is family-wide even though the card belongs to one child, so
* adult profiles stay out of it unless show_adults is set. The card's own
* child is always in it.
*/
_everyoneIds() {
const all = this._children();
const cfg = { ...this.config, child_id: undefined };
const listed = (window.__taskmate_family_children ? window.__taskmate_family_children(all, cfg) : all);
const me = String(this.config.child_id);
return listed.concat(all.filter(c => String(c.id) === me && !listed.includes(c))).map(c => c.id);
}

_eligible(b, childId) {
return !Array.isArray(b.eligible) || b.eligible.length === 0 || b.eligible.map(String).includes(String(childId));
}
Expand Down Expand Up @@ -349,7 +363,7 @@ class TaskMateBountyCard extends LitElement {

_row(b, me, now, holdingClaim) {
const mine = String(b.claimed_by || "") === me;
const eligibleIds = Array.isArray(b.eligible) && b.eligible.length ? b.eligible : this._children().map(c => c.id);
const eligibleIds = Array.isArray(b.eligible) && b.eligible.length ? b.eligible : this._everyoneIds();
const expLeft = b.expires_at ? this._msUntil(b.expires_at, now) : null;
const showMeta = b.status === "open" || b.status === "claimed";
let cls = "";
Expand Down Expand Up @@ -713,11 +727,13 @@ class TaskMateBountyCardEditor extends LitElement {
child_id: this._t("bounty.editor.child"),
title: this._t("common.editor.card_title"),
card_design: this._t("common.design.field_label"),
show_adults: this._t("common.editor.show_adults"),
}[entry.name] ?? entry.name);

_computeHelper = (entry) => ({
entity: this._t("common.editor.overview_entity_helper"),
child_id: this._t("bounty.editor.child_helper"),
show_adults: this._t("common.editor.show_adults_helper"),
}[entry.name] ?? "");

render() {
Expand All @@ -727,12 +743,13 @@ class TaskMateBountyCardEditor extends LitElement {
child_id: this.config.child_id || "",
title: this.config.title || "",
card_design: this.config.card_design || "global",
show_adults: this.config.show_adults === true,
};
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${this._buildSchema()}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
@value-changed=${this._formChanged}
Expand Down Expand Up @@ -761,7 +778,8 @@ class TaskMateBountyCardEditor extends LitElement {
const newConfig = { ...this.config };
for (const [key, value] of Object.entries(newValues)) {
// "global" is the absence of a per-card override, not a value to store.
if (value === "" || value === null || value === undefined || (key === "card_design" && value === "global")) {
if (value === "" || value === null || value === undefined || (key === "card_design" && value === "global")
|| (key === "show_adults" && value === false)) {
delete newConfig[key];
} else {
newConfig[key] = value;
Expand Down
2 changes: 1 addition & 1 deletion custom_components/taskmate/www/taskmate-calendar-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ class TaskMateCalendarCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
2 changes: 1 addition & 1 deletion custom_components/taskmate/www/taskmate-graph-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ class TaskMateGraphCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
10 changes: 8 additions & 2 deletions custom_components/taskmate/www/taskmate-incentive-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,9 @@ export function createIncentiveCard(P) {
}

_getChildren() {
return this._getAttrs().children || [];
// Adult profiles stay off the picker unless show_adults is set (#1071).
const all = this._getAttrs().children || [];
return (window.__taskmate_family_children ? window.__taskmate_family_children(all, this.config) : all);
}

_getBonuses() {
Expand Down Expand Up @@ -1095,6 +1097,7 @@ export function createIncentiveCard(P) {
title: this._t('common.editor.card_title'),
show_parent_actions: this._t('common.editor.show_parent_actions'),
card_design: this._t('common.design.field_label'),
show_adults: this._t('common.editor.show_adults'),
};
return labels[entry.name] ?? entry.name;
};
Expand All @@ -1103,6 +1106,7 @@ export function createIncentiveCard(P) {
const helpers = {
entity: this._t('common.editor.overview_entity_helper'),
show_parent_actions: this._t('common.editor.show_parent_actions_helper'),
show_adults: this._t('common.editor.show_adults_helper'),
};
return helpers[entry.name] ?? '';
};
Expand All @@ -1114,6 +1118,7 @@ export function createIncentiveCard(P) {
title: this.config.title || '',
show_parent_actions: this.config.show_parent_actions !== false,
card_design: this.config.card_design || 'global',
show_adults: this.config.show_adults === true,
};
return html`
<div class="info-note">
Expand All @@ -1123,7 +1128,7 @@ export function createIncentiveCard(P) {
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${this._buildSchema()}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
@value-changed=${this._formChanged}
Expand Down Expand Up @@ -1153,6 +1158,7 @@ export function createIncentiveCard(P) {
for (const [key, value] of Object.entries(newValues)) {
if (value === '' || value === null || value === undefined) delete newConfig[key];
else if (key === 'card_design' && value === 'global') delete newConfig[key];
else if (key === 'show_adults' && value === false) delete newConfig[key];
else newConfig[key] = value;
}
this._fire(newConfig);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ class TaskMateLeaderboardCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
2 changes: 1 addition & 1 deletion custom_components/taskmate/www/taskmate-overview-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ class TaskMateOverviewCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1537,7 +1537,7 @@ class TaskMateParentDashboardCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
2 changes: 1 addition & 1 deletion custom_components/taskmate/www/taskmate-points-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -1317,7 +1317,7 @@ class TaskMatePointsCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,7 @@ class TaskMatePointsDisplayCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ class TaskMateRewardProgressCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
68 changes: 49 additions & 19 deletions custom_components/taskmate/www/taskmate-rewards-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -1112,14 +1112,46 @@ class TaskMateRewardsCard extends LitElement {
// in-card selection to the first child so the claim button renders (and the
// child tabs have a selection). Without this, childId stays null and no claim
// button is ever shown, making rewards impossible to claim.
if (this.hass && this.config && !this.config.child_id && !this._selectedChildId) {
// Adult profiles (#1071): the default is the first family child, and a
// selection that's no longer listed (show_adults switched off) moves back.
if (this.hass && this.config && !this.config.child_id) {
const attrs = (window.__taskmate_attrs && window.__taskmate_attrs(this.hass, this.config.entity))
|| this.hass.states?.[this.config.entity]?.attributes || {};
const kids = attrs.children || [];
if (kids.length) this._selectedChildId = kids[0].id;
const kids = this._family(attrs.children || []);
if (kids.length && !kids.some((c) => c.id === this._selectedChildId)) this._selectedChildId = kids[0].id;
}
}

// The children a family-wide view lists (#1061/#1071): adults only with
// show_adults, and everyone when the card is pinned to a child_id.
_family(children) {
return (window.__taskmate_family_children ? window.__taskmate_family_children(children, this.config) : children);
}

/**
* Who a reward row lists (#1071). Non-jackpot rewards and the child badges
* follow the family filter. A jackpot's breakdown does too, except that an
* adult who has put points into it stays listed — dropping them would leave
* the segments and the total not adding up.
*/
_rewardPeople(reward, children) {
const assignedTo = reward.assigned_to || [];
const family = this._family(children);
const assigned = (c) => assignedTo.length === 0 || assignedTo.includes(c.id);
const relevantChildren = family.filter(assigned);
const listed = new Set(family.map((c) => c.id));
const hidden = new Set(children.filter((c) => !listed.has(c.id)).map((c) => c.id));
const allocations = reward.pool_allocations || {};
const contributors = relevantChildren.concat(
children.filter((c) => hidden.has(c.id) && assigned(c) && (allocations[c.id] || 0) !== 0)
);
return {
relevantChildren,
contributors,
badgeIds: assignedTo.filter((cid) => !hidden.has(cid)),
};
}

_selectChild(id) {
this._selectedChildId = id;
}
Expand Down Expand Up @@ -1234,7 +1266,7 @@ class TaskMateRewardsCard extends LitElement {
: ""}
</div>

${this._renderChildTabs(children)}
${this._renderChildTabs(this._family(children))}

${anyPoolReward && activeChild ? this._renderSpendableBanner(activeChild, pointsIcon, pointsName) : ''}

Expand Down Expand Up @@ -1361,10 +1393,8 @@ class TaskMateRewardsCard extends LitElement {
// All costs are static — just use reward.cost
const displayCost = this._getDisplayCost(reward);

// Get relevant children for this reward
const relevantChildren = assignedTo.length === 0
? children
: children.filter(c => assignedTo.includes(c.id));
// Get relevant children for this reward (family-filtered, #1071)
const { relevantChildren, contributors, badgeIds } = this._rewardPeople(reward, children);

// Determine active child context
const childId = this.config?.child_id || this._selectedChildId;
Expand All @@ -1381,7 +1411,7 @@ class TaskMateRewardsCard extends LitElement {
let childContributions = [];

if (isJackpot) {
relevantChildren.forEach((child, index) => {
contributors.forEach((child, index) => {
// In pool mode, show allocated points only; in wallet mode show wallet points
const points = enablePoolMode
? (poolAllocations[child.id] || 0)
Expand Down Expand Up @@ -1484,7 +1514,7 @@ class TaskMateRewardsCard extends LitElement {
<div class="assigned-children">
${assignedTo.length === 0
? html`<span class="child-badge all-children">${this._t('rewards.all_children')}</span>`
: assignedTo.map(
: badgeIds.map(
(cid) =>
html`<span class="child-badge">${childMap[cid] || cid}</span>`
)}
Expand Down Expand Up @@ -1858,7 +1888,6 @@ class TaskMateRewardsCard extends LitElement {
* _getDisplayCost — static only). Returns everything the designed rows need.
*/
_rewardData(reward, children) {
const assignedTo = reward.assigned_to || [];
const isJackpot = reward.is_jackpot || false;
const cardForcesPool = this.config.enable_pool_mode === true;
// Jackpot rewards are always pool-mode (#552): everyone deposits into the
Expand All @@ -1867,9 +1896,7 @@ class TaskMateRewardsCard extends LitElement {
const enablePoolMode = cardForcesPool || reward.pool_enabled === true || isJackpot;
const displayCost = this._getDisplayCost(reward);

const relevantChildren = assignedTo.length === 0
? children
: children.filter(c => assignedTo.includes(c.id));
const { relevantChildren, contributors } = this._rewardPeople(reward, children);

const childId = this.config?.child_id || this._selectedChildId;
const relevantChild = childId
Expand All @@ -1883,7 +1910,7 @@ class TaskMateRewardsCard extends LitElement {
const childContributions = [];

if (isJackpot) {
relevantChildren.forEach((child, index) => {
contributors.forEach((child, index) => {
const points = enablePoolMode
? (poolAllocations[child.id] || 0)
: (child.points || 0);
Expand Down Expand Up @@ -2006,7 +2033,7 @@ class TaskMateRewardsCard extends LitElement {
const body = sortedRewards.length === 0
? html`<div class="tmd-empty">${this._t('rewards.empty_title')}<br>${this._t('rewards.empty_subtitle')}</div>`
: html`
${this._designChildTabs(children)}
${this._designChildTabs(this._family(children))}
${(anyPoolReward && activeChild) || activeChild
? this._designChildSelector(activeChild, pointsIcon, pointsName, design)
: ''}
Expand Down Expand Up @@ -2064,7 +2091,7 @@ class TaskMateRewardsCard extends LitElement {
const badges = showChildBadges && !d.isJackpot
? (assignedTo.length === 0
? html`<span class="chip soft rw-badge rw-badge-all">${this._t('rewards.all_children')}</span>`
: assignedTo.map((cid) => html`<span class="chip rw-badge">${childMap[cid] || cid}</span>`))
: this._rewardPeople(reward, children).badgeIds.map((cid) => html`<span class="chip rw-badge">${childMap[cid] || cid}</span>`))
: '';

const costBadge = html`<span class="chip rw-cost"><ha-icon style="--mdc-icon-size:1.1em;vertical-align:-0.15em" icon="${pointsIcon}"></ha-icon> ${d.displayCost} ${pointsName}</span>`;
Expand Down Expand Up @@ -2353,6 +2380,7 @@ class TaskMateRewardsCardEditor extends LitElement {
show_child_badges: this._t('rewards.editor.show_child_badges'),
enable_pool_mode: this._t('rewards.editor.enable_pool_mode'),
expand_to_fit: this._t('rewards.editor.expand_to_fit'),
show_adults: this._t('common.editor.show_adults'),
};
return labels[schemaEntry.name] ?? schemaEntry.name;
};
Expand All @@ -2365,6 +2393,7 @@ class TaskMateRewardsCardEditor extends LitElement {
show_child_badges: this._t('rewards.editor.show_child_badges_helper'),
enable_pool_mode: this._t('rewards.editor.enable_pool_mode_helper'),
expand_to_fit: this._t('rewards.editor.expand_to_fit_helper'),
show_adults: this._t('common.editor.show_adults_helper'),
};
return helpers[schemaEntry.name] ?? '';
};
Expand All @@ -2382,13 +2411,14 @@ class TaskMateRewardsCardEditor extends LitElement {
show_child_badges: this.config.show_child_badges !== false,
enable_pool_mode: this.config.enable_pool_mode === true,
expand_to_fit: this.config.expand_to_fit !== false,
show_adults: this.config.show_adults === true,
};

return html`
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${this._buildSchema()}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
@value-changed=${this._formChanged}
Expand Down Expand Up @@ -2427,7 +2457,7 @@ class TaskMateRewardsCardEditor extends LitElement {
} else if (key === 'show_child_badges' && value === true) {
// Default is true — omit to keep config minimal
delete newConfig[key];
} else if (key === 'enable_pool_mode' && value === false) {
} else if ((key === 'enable_pool_mode' || key === 'show_adults') && value === false) {
delete newConfig[key];
} else if (key === 'expand_to_fit' && value === true) {
// Default is true (fluid) — omit to keep config minimal
Expand Down
2 changes: 1 addition & 1 deletion custom_components/taskmate/www/taskmate-streak-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ class TaskMateStreakCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
2 changes: 1 addition & 1 deletion custom_components/taskmate/www/taskmate-weekly-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ class TaskMateWeeklyCardEditor extends LitElement {
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.data=${this.config.show_adults === true ? { ...data, show_adults: true } : data}
.schema=${this._buildSchema().concat(window.__taskmate_adults_field ? window.__taskmate_adults_field(this.hass, this.config) : [])}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
Expand Down
Loading
Loading