(html`
diff --git a/src/elements/public/UserInvitationForm/UserInvitationForm.ts b/src/elements/public/UserInvitationForm/UserInvitationForm.ts
index 4333aff2..e5c9bcaa 100644
--- a/src/elements/public/UserInvitationForm/UserInvitationForm.ts
+++ b/src/elements/public/UserInvitationForm/UserInvitationForm.ts
@@ -21,6 +21,7 @@ export class UserInvitationForm extends Base {
...super.properties,
getStorePageHref: { attribute: false },
defaultDomain: { attribute: 'default-domain' },
+ currentUser: { attribute: 'current-user' },
layout: {},
};
}
@@ -62,6 +63,9 @@ export class UserInvitationForm extends Base {
/** Default host domain for stores that don't use a custom domain name, e.g. `foxycart.com`. */
defaultDomain: string | null = null;
+ /** Currently logged in user resource URL. Used to display a warning when revoking access. */
+ currentUser: string | null = null;
+
/** Admin layout will display user info, user layout (default) will display store info. */
layout: 'admin' | 'user' | null = null;
@@ -169,7 +173,7 @@ export class UserInvitationForm extends Base {
`;
}
- private __renderAdminSnapshotState({ first_name, last_name }: Data) {
+ private __renderAdminSnapshotState({ first_name, last_name, store_name, _links }: Data) {
const hasName = first_name?.trim() || last_name?.trim();
const nameOptions = { first_name, last_name, context: hasName ? '' : 'empty' };
const status = this.data?.status;
@@ -237,13 +241,30 @@ export class UserInvitationForm extends Base {
hidden.matches('resend', true) &&
hidden.matches('delete', true)}
>
-
-
+ ${this.currentUser && _links['fx:user'] && this.currentUser === _links['fx:user'].href
+ ? html`
+ this.dispatchEvent(new CustomEvent('selfrevoked'))}
+ >
+
+ `
+ : html`
+
+
+ `}
{
{ value: 'transaction', label: 'event_resource_transaction' },
{ value: 'transaction_log', label: 'event_resource_transaction_log' },
{ value: 'customer', label: 'event_resource_customer' },
+ { value: 'changelog', label: 'event_resource_changelog' },
];
expect(control).to.exist;
diff --git a/src/elements/public/WebhookForm/WebhookForm.ts b/src/elements/public/WebhookForm/WebhookForm.ts
index d2300436..90349342 100644
--- a/src/elements/public/WebhookForm/WebhookForm.ts
+++ b/src/elements/public/WebhookForm/WebhookForm.ts
@@ -55,6 +55,7 @@ export class WebhookForm extends TranslatableMixin(InternalForm, 'webhook-form')
{ value: 'transaction', label: 'event_resource_transaction' },
{ value: 'transaction_log', label: 'event_resource_transaction_log' },
{ value: 'customer', label: 'event_resource_customer' },
+ { value: 'changelog', label: 'event_resource_changelog' },
];
get hiddenSelector(): BooleanSelector {
diff --git a/src/static/translations/admin-subscription-form/en.json b/src/static/translations/admin-subscription-form/en.json
index f753587b..818a8318 100644
--- a/src/static/translations/admin-subscription-form/en.json
+++ b/src/static/translations/admin-subscription-form/en.json
@@ -37,10 +37,13 @@
"cancel": "Close",
"cancel_title": "Cancel this subscription",
"cancel_subtitle": "Cancelling subscriptions in Foxy works by setting the end date. You can select any date in the future, starting from tomorrow.",
+ "cancel_subtitle_future": "Cancelling subscriptions in Foxy works by setting the end date. You can select any date in the future, beginning from the start date.",
"cancel_why_not_today_title": "Why can't I select today as the end date?",
"cancel_why_not_today_text": "Same-day cancellations may disrupt billing due to ongoing payment processing. Advance notice ensures that all transactions are completed before cancellation.",
+ "cancel_why_not_today_text_future": "Subscriptions that haven't started yet won't be processed until their start date. Therefore, the earliest end date you can select is the start date.",
"cancel_whats_next_title": "What happens next?",
"cancel_whats_next_text": "The subscription will remain active and all payments will be processed as usual until the end date. On the end date, the subscription will be cancelled and no further payments will be taken. If the end date is the same as a normal renewal date, no payments will be taken, but the subscription will simply be cancelled.",
+ "cancel_whats_next_text_future": "The subscription will not be processed until the start date. On the end date, the subscription will be cancelled and no payments will be taken. If the end date is the same as the start date, no payments will be taken, but the subscription will simply be cancelled.",
"cancel_how_to_reactivate_title": "Can I reactivate this subscription later?",
"cancel_how_to_reactivate_text": "Yes, you will be able to clear the pending cancellation before the end date, or reactivate the subscription after the end date on this page.",
"cancel_submit": "Cancel this subscription",
@@ -55,6 +58,7 @@
"label": "Cancel this subscription",
"helper_text": "",
"placeholder": "Select",
+ "option_start_date": "On start date",
"option_tomorrow": "Tomorrow",
"option_next_transaction_date": "On next renewal date",
"option_custom_date": "On specific date"
@@ -1283,6 +1287,8 @@
"total_tax": "Tax",
"subtotal": "Subtotal",
"total": "Total",
+ "refundable_amount": "Refundable",
+ "refundable_amount_note": "The amount that can be refunded is different from the order total above because this transaction has been modified",
"price": "{{amount, price}}",
"status_capturing": "Capturing",
"status_captured": "Captured",
@@ -1291,7 +1297,7 @@
"status_pending": "Pending",
"status_completed": "Completed",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Pending fraud review",
"status_rejected": "Rejected",
"status_declined": "Declined",
"status_refunding": "Refunding",
@@ -2103,7 +2109,7 @@
"button": "Void"
},
"refund": {
- "message_idle": "This action will attempt to refund the full amount of this transaction. Would you like to proceed?",
+ "message_idle": "This action will attempt to refund {{ amount, price }} to the payment method used in this transaction. Would you like to proceed?",
"message_fail": "Failed to refund this transaction. If you'd like to retry, close this dialog and click the refund button again.",
"message_done": "Transaction was refunded successfully. You can close this dialog now.",
"button_close": "Close",
diff --git a/src/static/translations/coupon-form/en.json b/src/static/translations/coupon-form/en.json
index a2b62598..5a1d9e60 100644
--- a/src/static/translations/coupon-form/en.json
+++ b/src/static/translations/coupon-form/en.json
@@ -252,7 +252,7 @@
"status_pending": "Pending",
"status_completed": "Completed",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Pending fraud review",
"status_rejected": "Rejected",
"status_declined": "Declined",
"status_refunding": "Refunding",
diff --git a/src/static/translations/customer-portal/de.json b/src/static/translations/customer-portal/de.json
index b7d1e9e9..ad9bd0d6 100644
--- a/src/static/translations/customer-portal/de.json
+++ b/src/static/translations/customer-portal/de.json
@@ -1086,7 +1086,7 @@
"status_pending": "Ausstehend",
"status_completed": "Vollendet",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Ausstehende Betrugsüberprüfung",
"status_rejected": "Abgelehnt",
"status_declined": "Abgelehnt",
"status_refunding": "Rückerstattung",
diff --git a/src/static/translations/customer-portal/en.json b/src/static/translations/customer-portal/en.json
index 02ee4078..472df910 100644
--- a/src/static/translations/customer-portal/en.json
+++ b/src/static/translations/customer-portal/en.json
@@ -1086,7 +1086,7 @@
"status_pending": "Pending",
"status_completed": "Completed",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Pending fraud review",
"status_rejected": "Rejected",
"status_declined": "Declined",
"status_refunding": "Refunding",
diff --git a/src/static/translations/customer-portal/sv.json b/src/static/translations/customer-portal/sv.json
index 3bc4504b..f4d42e59 100644
--- a/src/static/translations/customer-portal/sv.json
+++ b/src/static/translations/customer-portal/sv.json
@@ -1086,7 +1086,7 @@
"status_pending": "I väntan på",
"status_completed": "Avslutad",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Väntar på bedrägeriskontroll",
"status_rejected": "avvisade",
"status_declined": "Tackade nej",
"status_refunding": "Återbetalning",
diff --git a/src/static/translations/customer/en.json b/src/static/translations/customer/en.json
index 487c4b22..d6cff23e 100644
--- a/src/static/translations/customer/en.json
+++ b/src/static/translations/customer/en.json
@@ -1271,7 +1271,7 @@
"status_pending": "Pending",
"status_completed": "Completed",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Pending fraud review",
"status_rejected": "Rejected",
"status_declined": "Declined",
"status_refunding": "Refunding",
diff --git a/src/static/translations/subscription-form/en.json b/src/static/translations/subscription-form/en.json
index 23d7ee55..67f4e585 100644
--- a/src/static/translations/subscription-form/en.json
+++ b/src/static/translations/subscription-form/en.json
@@ -195,7 +195,7 @@
"status_pending": "Pending",
"status_completed": "Completed",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Pending fraud review",
"status_rejected": "Rejected",
"status_declined": "Declined",
"status_refunding": "Refunding",
diff --git a/src/static/translations/transaction-card/en.json b/src/static/translations/transaction-card/en.json
index 2a3df320..a4aa55b7 100644
--- a/src/static/translations/transaction-card/en.json
+++ b/src/static/translations/transaction-card/en.json
@@ -13,7 +13,7 @@
"status_pending": "Pending",
"status_completed": "Completed",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Pending fraud review",
"status_rejected": "Rejected",
"status_declined": "Declined",
"status_refunding": "Refunding",
diff --git a/src/static/translations/transaction/en.json b/src/static/translations/transaction/en.json
index 82350e0e..2f471734 100644
--- a/src/static/translations/transaction/en.json
+++ b/src/static/translations/transaction/en.json
@@ -920,6 +920,8 @@
"total_tax": "Tax",
"subtotal": "Subtotal",
"total": "Total",
+ "refundable_amount": "Refundable",
+ "refundable_amount_note": "The amount that can be refunded is different from the order total above because this transaction has been modified",
"price": "{{amount, price}}",
"status_capturing": "Capturing",
"status_captured": "Captured",
@@ -928,7 +930,7 @@
"status_pending": "Pending",
"status_completed": "Completed",
"status_problem": "Problem",
- "status_pending_fraud_review": "Pending_fraud_review",
+ "status_pending_fraud_review": "Pending fraud review",
"status_rejected": "Rejected",
"status_declined": "Declined",
"status_refunding": "Refunding",
@@ -1740,7 +1742,7 @@
"button": "Void"
},
"refund": {
- "message_idle": "This action will attempt to refund the full amount of this transaction. Would you like to proceed?",
+ "message_idle": "This action will attempt to refund {{ amount, price }} to the payment method used in this transaction. Would you like to proceed?",
"message_fail": "Failed to refund this transaction. If you'd like to retry, close this dialog and click the refund button again.",
"message_done": "Transaction was refunded successfully. You can close this dialog now.",
"button_close": "Close",
diff --git a/src/static/translations/user-invitation-form/en.json b/src/static/translations/user-invitation-form/en.json
index d2dc8c36..f7455dcb 100644
--- a/src/static/translations/user-invitation-form/en.json
+++ b/src/static/translations/user-invitation-form/en.json
@@ -32,7 +32,16 @@
"revoke": {
"idle": "Revoke access",
"busy": "Revoking...",
- "fail": "Failed to revoke"
+ "fail": "Failed to revoke",
+ "message_idle": "You are about to remove your own access to {{ store_name }} ({{ store_domain }}). Are you sure you want to proceed? If you need access to this store again in the future, you will need to be re-invited by another user of the store.",
+ "message_fail": "Failed to revoke access. If you'd like to retry, close this dialog and click the revoke button again.",
+ "message_done": "Your access was revoked successfully. Close this dialog to continue.",
+ "button_close": "Close",
+ "button_confirm": "Leave this store",
+ "button_cancel": "Cancel",
+ "loading_busy": "Processing",
+ "header": "Confirmation Required",
+ "button": "Revoke access"
},
"resend": {
"idle": "Resend invitation",
diff --git a/src/static/translations/webhook-form/en.json b/src/static/translations/webhook-form/en.json
index 4034e6da..f7852047 100644
--- a/src/static/translations/webhook-form/en.json
+++ b/src/static/translations/webhook-form/en.json
@@ -9,6 +9,7 @@
"subtitle_transaction_log": "Transaction log webhook",
"subtitle_subscription": "Subscription webhook",
"subtitle_customer": "Customer webhook",
+ "subtitle_changelog": "Changelog webhook",
"copy-id": {
"failed_to_copy": "Failed to copy",
"click_to_copy": "Copy ID",
@@ -50,7 +51,8 @@
"event_resource_transaction_log": "Transaction log",
"event_resource_subscription": "Subscription",
"event_resource_transaction": "Transaction",
- "event_resource_customer": "Customer"
+ "event_resource_customer": "Customer",
+ "event_resource_changelog": "Changelog"
},
"url": {
"label": "Endpoint",
diff --git a/src/utils/parse-date.ts b/src/utils/parse-date.ts
index 2e76be60..83588983 100644
--- a/src/utils/parse-date.ts
+++ b/src/utils/parse-date.ts
@@ -1,6 +1,8 @@
+import { safeDate } from './safe-date';
+
export function parseDate(strDate: string): Date | null {
if (strDate === '0000-00-00') return null;
const [year, month, day] = strDate.split('-').map(v => parseInt(v, 10));
if ([year, month, day].some(v => typeof v !== 'number' || isNaN(v))) return null;
- return new Date(year, month - 1, day);
+ return safeDate(year, month - 1, day);
}
diff --git a/src/utils/safe-date.ts b/src/utils/safe-date.ts
new file mode 100644
index 00000000..36d1e42e
--- /dev/null
+++ b/src/utils/safe-date.ts
@@ -0,0 +1,8 @@
+export function safeDate(year: number, month: number, day?: number): Date {
+ // 0-99 map to 1900-1999 in JS Date, so we need to use
+ // setFullYear to set the correct year.
+ const date = new Date();
+ date.setFullYear(year, month, day);
+ date.setHours(0, 0, 0, 0);
+ return date;
+}