Skip to content

Commit 02636c2

Browse files
authored
Merge pull request #6318 from frappe/release/2026-W19
chore: Release release/2026-W19
2 parents d456ae2 + 74068e3 commit 02636c2

62 files changed

Lines changed: 2241 additions & 315 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.secrets.baseline

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,14 +287,14 @@
287287
"filename": "press/api/tests/test_marketplace.py",
288288
"hashed_secret": "1e2a4c3be8ec693658961500ff918de4c188b4f1",
289289
"is_verified": false,
290-
"line_number": 61
290+
"line_number": 71
291291
},
292292
{
293293
"type": "Hex High Entropy String",
294294
"filename": "press/api/tests/test_marketplace.py",
295295
"hashed_secret": "a6362a1031d1d2039364ea6b51694151bf388a40",
296296
"is_verified": false,
297-
"line_number": 69
297+
"line_number": 79
298298
}
299299
],
300300
"press/auth.py": [
@@ -524,5 +524,5 @@
524524
}
525525
]
526526
},
527-
"generated_at": "2026-04-24T17:21:58Z"
527+
"generated_at": "2026-04-28T10:45:30Z"
528528
}

dashboard/src/components/CustomAlerts.vue

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,28 @@
44
v-for="banner in localBanners"
55
:key="banner.name"
66
:class="disableLastChildBottomMargin ? `mb-5 last:mb-0` : `mb-5`"
7-
:title="`<b>${banner.title}:</b> ${banner.message}`"
7+
:title="getAlertTitle(banner.title, banner.message)"
88
:type="banner.type.toLowerCase()"
99
:isDismissible="banner.is_dismissible"
1010
@dismissBanner="closeBanner(banner.name)"
1111
>
12-
<template v-if="!!banner.help_url">
12+
<template
13+
v-if="
14+
!!banner.help_url ||
15+
(banner.has_action && banner.action_label && banner.action_script)
16+
"
17+
>
1318
<Button
14-
class="ml-auto flex flex-row items-center gap-1"
15-
@click="openHelp(banner.help_url)"
19+
size="sm"
20+
class="ml-auto flex flex-row items-center gap-x-1"
21+
@click="
22+
banner.has_action
23+
? exec(banner.action_script)
24+
: openHelp(banner.help_url)
25+
"
1626
variant="outline"
1727
>
18-
Open help
28+
{{ banner.has_action ? banner.action_label : 'Open help' }}
1929
<lucide-external-link class="inline h-4 w-3 pb-0.5" />
2030
</Button>
2131
</template>
@@ -36,10 +46,13 @@ export default {
3646
validator: (value) => !value || ['Site', 'Server'].includes(value),
3747
},
3848
ctx_name: {
39-
type: String,
4049
required: false,
4150
validator: (value) =>
42-
!value || (typeof value === 'string' && value.length > 0),
51+
!value ||
52+
(typeof value === 'string' && value.length > 0) ||
53+
(Array.isArray(value) &&
54+
value.every((el) => typeof el === 'string') &&
55+
value.length > 0),
4356
},
4457
containerClass: {
4558
type: String,
@@ -58,7 +71,23 @@ export default {
5871
localDismissedBanners: {},
5972
};
6073
},
74+
computed: {
75+
ctxNames() {
76+
return Array.isArray(this.ctx_name)
77+
? this.ctx_name
78+
: this.ctx_name
79+
? [this.ctx_name]
80+
: [];
81+
},
82+
},
6183
methods: {
84+
getAlertTitle(bannerTitle, bannerMessage) {
85+
let str = '';
86+
if (bannerTitle) str = str.concat(`<b>${bannerTitle}</b>`);
87+
if (!!bannerTitle && !!bannerMessage) str = str.concat(': ');
88+
if (bannerMessage) str = str.concat(bannerMessage);
89+
return str;
90+
},
6291
closeBanner(bannerName) {
6392
const banner = this.localBanners.find((b) => b.name === bannerName);
6493
if (!banner) return;
@@ -67,7 +96,7 @@ export default {
6796
(b) => b.name !== bannerName,
6897
);
6998
70-
if (banner.is_global) {
99+
if (banner.is_global || banner.type_of_scope == 'Cluster') {
71100
// Persist dismissal to local storage
72101
this.localDismissedBanners[bannerName] = Date.now();
73102
localStorage.setItem(
@@ -82,16 +111,23 @@ export default {
82111
openHelp(url) {
83112
window.open(url, '_blank');
84113
},
114+
exec(action_script) {
115+
const actionFn = new Function(
116+
'_this',
117+
action_script + '\nonClickAction(_this)',
118+
);
119+
actionFn(this);
120+
},
85121
trimOldDismissedBanners() {
86-
// Remove dismissed banners older than 30 days from local storage
87-
const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000;
122+
// Remove dismissed banners older than 60 days from local storage
123+
const SIXTY_DAYS_IN_MS = 60 * 24 * 60 * 60 * 1000;
88124
const now = Date.now();
89125
let diff = false;
90126
91127
for (const [bannerName, timestamp] of Object.entries(
92128
this.localDismissedBanners,
93129
)) {
94-
if (now - timestamp > THIRTY_DAYS) {
130+
if (now - timestamp > SIXTY_DAYS_IN_MS) {
95131
delete this.localDismissedBanners[bannerName];
96132
diff = true;
97133
}
@@ -104,6 +140,34 @@ export default {
104140
);
105141
}
106142
},
143+
isRelevantBanner(banner) {
144+
if (banner.is_global) return true;
145+
146+
const ctxMatches = (list) =>
147+
Array.isArray(list) &&
148+
list.some((item) => this.ctxNames.includes(item));
149+
150+
switch (this.ctx_type) {
151+
case 'Server':
152+
return (
153+
(banner.type_of_scope === 'Server' && ctxMatches(banner.server)) ||
154+
(banner.type_of_scope === 'Cluster' && ctxMatches(banner.cluster))
155+
);
156+
157+
case 'Site':
158+
return (
159+
(banner.type_of_scope === 'Site' && ctxMatches(banner.site)) ||
160+
(banner.type_of_scope === 'Server' && ctxMatches(banner.server)) ||
161+
(banner.type_of_scope === 'Cluster' && ctxMatches(banner.cluster))
162+
);
163+
164+
case 'List Page':
165+
return ['Team', 'Cluster', 'Server'].includes(banner.type_of_scope);
166+
167+
default:
168+
return true;
169+
}
170+
},
107171
},
108172
resources: {
109173
banners() {
@@ -126,24 +190,10 @@ export default {
126190
127191
this.trimOldDismissedBanners();
128192
129-
this.localBanners = (
130-
this.ctx_type === 'Server'
131-
? data.filter(
132-
(banner) =>
133-
banner.server === this.ctx_name || banner.is_global,
134-
)
135-
: this.ctx_type === 'Site'
136-
? data.filter(
137-
(banner) =>
138-
banner.site === this.ctx_name || banner.is_global,
139-
)
140-
: this.ctx_type === 'List Page'
141-
? data.filter(
142-
(banner) =>
143-
banner.type_of_scope === 'Team' || banner.is_global,
144-
)
145-
: data
146-
).filter((banner) => !(banner.name in this.localDismissedBanners));
193+
this.localBanners = data
194+
.filter(this.isRelevantBanner)
195+
.filter((banner) => banner.title || banner.message)
196+
.filter((banner) => !(banner.name in this.localDismissedBanners));
147197
},
148198
};
149199
},

dashboard/src/components/SiteOverview.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:disable-last-child-bottom-margin="true"
88
container-class="col-span-1 lg:col-span-2"
99
ctx_type="Site"
10-
:ctx_name="$site?.doc?.name"
10+
:ctx_name="[$site?.doc?.name, $site?.doc.server, $site?.doc?.cluster]"
1111
/>
1212
<AlertBanner
1313
v-if="$site?.doc?.creation_failed"

dashboard/src/components/billing/PaymentDetails.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,11 @@ function updatePaymentMode(mode) {
401401
return;
402402
}
403403
if (mode === 'UPI Autopay') {
404-
router.push({ name: 'BillingUPIAutopay' });
404+
if (team.doc.default_razorpay_mandate) {
405+
if (!changePaymentMode.loading) changePaymentMode.submit({ mode });
406+
} else {
407+
router.push({ name: 'BillingUPIAutopay' });
408+
}
405409
return;
406410
}
407411
if (!changePaymentMode.loading) changePaymentMode.submit({ mode });

0 commit comments

Comments
 (0)