Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: release 1.39.0 #201

Merged
merged 22 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0803b4c
fix: fix start/end/next/failure date priority in subscription summaries
pheekus Feb 6, 2025
ef99ec6
feat: add support for `is_active` switch to webhook elements
pheekus Feb 6, 2025
15822f2
chore: regenerate custom-elements.json
pheekus Feb 6, 2025
c33d5c9
fix(foxy-webhook-card): fix an error when loading freshly created web…
pheekus Feb 6, 2025
52cc17f
fix(foxy-webhook-card): show latest run status instead of the first one
pheekus Feb 7, 2025
ab42b51
feat(foxy-webhook-card): show last run date
pheekus Feb 7, 2025
a0ebc08
fix(foxy-webhook-status-card): add missing language string for `initi…
pheekus Feb 7, 2025
3cc08e6
fix(foxy-store-shipping-method-form): hide account fields for UPS
pheekus Feb 10, 2025
6ba8b96
refactor(foxy-customer-portal): update subscriptions ui
pheekus Feb 11, 2025
7ed6dab
build: temporarily bundle unreleased sdk
pheekus Feb 12, 2025
8012af1
feat(foxy-subscription-form): apply cart display config in customer p…
pheekus Feb 12, 2025
7805326
feat(foxy-item-card): apply cart display config in customer portal mode
pheekus Feb 12, 2025
2730aad
feat(foxy-subscription-card): apply cart display config in customer p…
pheekus Feb 12, 2025
1688462
feat(foxy-customer-portal): apply cart display config to subscription…
pheekus Feb 12, 2025
57bb0a3
test(foxy-customer-form): fix tests
pheekus Feb 12, 2025
82a5ba6
build: update to latest sdk
pheekus Feb 12, 2025
9683e29
feat(foxy-store-form): add support for switching between string and j…
pheekus Feb 13, 2025
5e2e658
fix(foxy-customer-portal): hide password reset screen on success
pheekus Feb 13, 2025
1c3f0cf
fix(foxy-item-card): hide all product options when cart display confi…
pheekus Feb 14, 2025
aea932e
fix(foxy-store-form): adjust store secret validations and add read-on…
pheekus Feb 14, 2025
8699ba1
fix(foxy-store-form): adjust secret generator options
pheekus Feb 14, 2025
7cced31
chore: regenerate custom-elements.json
pheekus Feb 14, 2025
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
287 changes: 287 additions & 0 deletions custom-elements.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"prepack": "npm run lint && rimraf dist && node ./.build/compile-for-npm.js && rollup -c"
},
"dependencies": {
"@foxy.io/sdk": "^1.13.0",
"@foxy.io/sdk": "^1.14.0",
"@open-wc/lit-helpers": "^0.3.12",
"@open-wc/scoped-elements": "^1.2.1",
"@polymer/iron-icons": "^3.0.1",
Expand Down
4 changes: 2 additions & 2 deletions src/elements/private/Group/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ export class Group extends LitElement {
public frame = false;

public render(): TemplateResult {
const frameClass = 'border border-contrast-10 overflow-hidden';
const frameClass = 'bg-contrast-5 overflow-hidden';

return html`
<section class="space-y-s font-lumo antialiased">
<h3 class=${`text-s font-medium text-secondary leading-none ${this.frame ? '' : 'pl-m'}`}>
<h3 class=${`text-l font-medium text-body leading-none ${this.frame ? '' : 'pl-m'}`}>
<slot name="header"></slot>
</h3>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getTestData } from '../../../testgen/getTestData';
import { FetchEvent } from '../NucleonElement/FetchEvent';
import { getByKey } from '../../../testgen/getByKey';
import { parseFrequency } from '../../../utils/parse-frequency';
import { getSubscriptionStatus } from '../../../utils/get-subscription-status';

describe('AdminSubscriptionCard', () => {
it('imports and registers foxy-i18n element', () => {
Expand Down Expand Up @@ -488,7 +489,7 @@ describe('AdminSubscriptionCard', () => {
expect(price?.options.amount.split(' ')[1]).to.equal('PKR');
});

it('renders a special status in line 2 for failed subscriptions', async () => {
it('renders subscription status in line 2', async () => {
const router = createRouter();
const href = 'https://demo.api/hapi/subscriptions/0';
const data = await getTestData<Resource<Rels.Subscription>>(href, router);
Expand All @@ -501,150 +502,13 @@ describe('AdminSubscriptionCard', () => {
</foxy-admin-subscription-card>
`);

data.first_failed_transaction_date = new Date(2022, 1, 1).toISOString();
data.start_date = new Date(2020, 1, 1).toISOString();
data.is_active = true;
data.end_date = null;
element.data = data;

await waitUntil(() => element.isBodyReady, '', { timeout: 5000 });
const price = await getByKey(element, 'subscription_failed');

expect(price).to.exist;
expect(price).to.have.attribute('infer', '');
expect(price).to.have.nested.property('options.date', data.first_failed_transaction_date);
});

it('renders a special status in line 2 for active subscriptions with an end date in the future', async () => {
const router = createRouter();
const href = 'https://demo.api/hapi/subscriptions/0';
const data = await getTestData<Resource<Rels.Subscription>>(href, router);

const element = await fixture<Card>(html`
<foxy-admin-subscription-card
locale-codes="https://demo.api/hapi/property_helpers/7"
@fetch=${(evt: FetchEvent) => router.handleEvent(evt)}
>
</foxy-admin-subscription-card>
`);

data.first_failed_transaction_date = null;
data.start_date = new Date(2020, 1, 1).toISOString();
data.is_active = true;
data.end_date = new Date(Date.now() + 2.628e9).toISOString();
element.data = data;

await waitUntil(() => element.isBodyReady, '', { timeout: 5000 });
const price = await getByKey(element, 'subscription_will_be_cancelled');

expect(price).to.exist;
expect(price).to.have.attribute('infer', '');
expect(price).to.have.nested.property('options.date', data.end_date);
});

it('renders a special status in line 2 for subscriptions that have ended', async () => {
const router = createRouter();
const href = 'https://demo.api/hapi/subscriptions/0';
const data = await getTestData<Resource<Rels.Subscription>>(href, router);

const element = await fixture<Card>(html`
<foxy-admin-subscription-card
locale-codes="https://demo.api/hapi/property_helpers/7"
@fetch=${(evt: FetchEvent) => router.handleEvent(evt)}
>
</foxy-admin-subscription-card>
`);

data.first_failed_transaction_date = null;
data.start_date = new Date(2020, 1, 1).toISOString();
data.is_active = true;
data.end_date = new Date(2022, 1, 1).toISOString();
element.data = data;

await waitUntil(() => element.isBodyReady, '', { timeout: 5000 });
const price = await getByKey(element, 'subscription_cancelled');
const status = await getByKey(element, `status_${getSubscriptionStatus(data)}`);

expect(price).to.exist;
expect(price).to.have.attribute('infer', '');
expect(price).to.have.nested.property('options.date', data.end_date);
});

it('renders a special status in line 2 for inactive subscriptions', async () => {
const router = createRouter();
const href = 'https://demo.api/hapi/subscriptions/0';
const data = await getTestData<Resource<Rels.Subscription>>(href, router);

const element = await fixture<Card>(html`
<foxy-admin-subscription-card
locale-codes="https://demo.api/hapi/property_helpers/7"
@fetch=${(evt: FetchEvent) => router.handleEvent(evt)}
>
</foxy-admin-subscription-card>
`);

data.first_failed_transaction_date = null;
data.start_date = new Date(2020, 1, 1).toISOString();
data.is_active = false;
data.end_date = null;
element.data = data;

await waitUntil(() => element.isBodyReady, '', { timeout: 5000 });
const price = await getByKey(element, 'subscription_inactive');

expect(price).to.exist;
expect(price).to.have.attribute('infer', '');
});

it('renders a special status in line 2 for active subscriptions', async () => {
const router = createRouter();
const href = 'https://demo.api/hapi/subscriptions/0';
const data = await getTestData<Resource<Rels.Subscription>>(href, router);

const element = await fixture<Card>(html`
<foxy-admin-subscription-card
locale-codes="https://demo.api/hapi/property_helpers/7"
@fetch=${(evt: FetchEvent) => router.handleEvent(evt)}
>
</foxy-admin-subscription-card>
`);

data.first_failed_transaction_date = null;
data.start_date = new Date(2020, 1, 1).toISOString();
data.is_active = true;
data.end_date = null;
element.data = data;

await waitUntil(() => element.isBodyReady, '', { timeout: 5000 });
const price = await getByKey(element, 'subscription_active');

expect(price).to.exist;
expect(price).to.have.attribute('infer', '');
});

it('renders a special status in line 2 for subscriptions that start soon', async () => {
const router = createRouter();
const href = 'https://demo.api/hapi/subscriptions/0';
const data = await getTestData<Resource<Rels.Subscription>>(href, router);

const element = await fixture<Card>(html`
<foxy-admin-subscription-card
locale-codes="https://demo.api/hapi/property_helpers/7"
@fetch=${(evt: FetchEvent) => router.handleEvent(evt)}
>
</foxy-admin-subscription-card>
`);

data.first_failed_transaction_date = null;
data.start_date = new Date(Date.now() + 3600000).toISOString();
data.is_active = true;
data.end_date = null;
element.data = data;

await waitUntil(() => element.isBodyReady, '', { timeout: 5000 });
const price = await getByKey(element, 'subscription_will_be_active');

expect(price).to.exist;
expect(price).to.have.attribute('infer', '');
expect(status).to.exist;
expect(status).to.have.attribute('infer', '');
expect(status).to.have.deep.property('options', data);
});

it('renders customer email in line 3 from embedded fx:transaction_template', async () => {
Expand Down
39 changes: 5 additions & 34 deletions src/elements/public/AdminSubscriptionCard/AdminSubscriptionCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Resource } from '@foxy.io/sdk/core';
import type { Rels } from '@foxy.io/sdk/backend';
import type { Data } from './types';

import { getSubscriptionStatus } from '../../../utils/get-subscription-status';
import { TranslatableMixin } from '../../../mixins/translatable';
import { ConfigurableMixin } from '../../../mixins/configurable';
import { parseFrequency } from '../../../utils/parse-frequency';
Expand Down Expand Up @@ -52,16 +53,14 @@ export class AdminSubscriptionCard extends Base<Data> {
private readonly __storeLoaderId = 'storeLoader';

renderBody(): TemplateResult {
const isFailed = !!this.data?.first_failed_transaction_date;
const customer = this.__customer;
const cart = this.__transactionTemplate;

const priceKey = this.__priceKey;
const priceOptions = this.__priceOptions;
const summaryOptions = this.__summaryOptions;
const summaryKey = this.__summaryKey;
const statusKey = this.__statusKey;
const statusOptions = this.__statusOptions;
const status = getSubscriptionStatus(this.data);

return html`
<foxy-nucleon
Expand Down Expand Up @@ -141,9 +140,9 @@ export class AdminSubscriptionCard extends Base<Data> {
</span>
</div>

<div class="truncate text-s ${isFailed ? 'text-error' : 'text-secondary'}">
${statusOptions && statusKey
? html`<foxy-i18n infer="" key=${statusKey} .options=${statusOptions}></foxy-i18n>`
<div class="truncate text-s ${status === 'failed' ? 'text-error' : 'text-secondary'}">
${this.data && status
? html`<foxy-i18n infer="" key="status_${status}" .options=${this.data}></foxy-i18n>`
: html`&ZeroWidthSpace;`}
</div>

Expand Down Expand Up @@ -315,18 +314,6 @@ export class AdminSubscriptionCard extends Base<Data> {
if (items) return items.isApproximateCount ? 'summary_approximate' : 'summary';
}

private get __statusOptions() {
const data = this.data;

if (data === null) return;
if (data.first_failed_transaction_date) return { date: data.first_failed_transaction_date };
if (data.end_date) return { date: data.end_date };
if (data.is_active === false) return {};
if (new Date(data.start_date) > new Date()) return { date: data.start_date };

return { date: data.next_transaction_date };
}

private get __currencyCode() {
const cart = this.__transactionTemplate;

Expand Down Expand Up @@ -361,22 +348,6 @@ export class AdminSubscriptionCard extends Base<Data> {
};
}

private get __statusKey() {
const data = this.data;

if (data === null) return;
if (data.first_failed_transaction_date) return 'subscription_failed';
if (data.end_date) {
const hasEnded = new Date(data.end_date).getTime() > Date.now();
return hasEnded ? 'subscription_will_be_cancelled' : 'subscription_cancelled';
}

if (data.is_active === false) return 'subscription_inactive';
if (new Date(data.start_date) > new Date()) return 'subscription_will_be_active';

return 'subscription_active';
}

private get __priceKey() {
const frequency = this.data?.frequency;
if (frequency) return `price_${frequency === '.5m' ? 'twice_a_month' : 'recurring'}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Data } from './types';

import { html, expect, fixture, waitUntil } from '@open-wc/testing';
import { AdminSubscriptionForm as Form } from './AdminSubscriptionForm';

import { getSubscriptionStatus } from '../../../utils/get-subscription-status';
import { createRouter } from '../../../server/index';
import { getTestData } from '../../../testgen/getTestData';

Expand Down Expand Up @@ -104,18 +104,14 @@ describe('AdminSubscriptionForm', () => {
expect(form.hiddenSelector.matches('cancel-action', true)).to.be.false;
});

it('uses custom subtitle options based on the subscription status', async () => {
const form = new Form();
expect(form.headerSubtitleOptions).to.deep.equal({ context: 'inactive' });

it('uses custom subtitle key based on the subscription status', async () => {
const testData = await getTestData<Data>('./hapi/subscriptions/0?zoom=transaction_template');
testData.is_active = true;
form.data = testData;
expect(form.headerSubtitleOptions).to.deep.equal({ context: 'active' });
const status = getSubscriptionStatus(testData);

testData.is_active = false;
const form = new Form();
form.data = testData;
expect(form.headerSubtitleOptions).to.deep.equal({ context: 'inactive' });

expect(form.headerSubtitleKey).to.equal(`subtitle_${status}`);
});

it('renders error message control', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { PropertyDeclarations } from 'lit-element';
import type { TemplateResult } from 'lit-html';
import type { Data } from './types';

import { getSubscriptionStatus } from '../../../utils/get-subscription-status';
import { TranslatableMixin } from '../../../mixins/translatable';
import { BooleanSelector } from '@foxy.io/sdk/core';
import { InternalForm } from '../../internal/InternalForm/InternalForm';
Expand Down Expand Up @@ -29,8 +30,9 @@ export class AdminSubscriptionForm extends Base<Data> {
return new BooleanSelector(alwaysMatch.join(' ').trim());
}

get headerSubtitleOptions(): Record<string, unknown> {
return { context: this.data?.is_active ? 'active' : 'inactive' };
get headerSubtitleKey(): string {
const status = getSubscriptionStatus(this.data);
return status ? `subtitle_${status}` : super.headerSubtitleKey;
}

renderBody(): TemplateResult {
Expand Down
11 changes: 11 additions & 0 deletions src/elements/public/CustomerForm/CustomerForm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ const portalSettings = {
allow_next_date_modification: false,
},
session_lifespan_in_minutes: 40320,
cart_display_config: {
show_product_weight: true,
show_product_category: true,
show_product_code: true,
show_product_options: true,
show_sub_frequency: true,
show_sub_startdate: true,
show_sub_nextdate: true,
show_sub_enddate: true,
hidden_product_options: [],
},
tos_checkbox_settings: {
usage: 'optional' as const,
url: 'https://foxy.io/terms-of-service/',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ export class InternalCustomerPortalLink extends ThemeableMixin(LitElement) {

render(): TemplateResult {
const actionClass = classMap({
'flex-auto font-medium tracking-wide text-s rounded-s transition-colors': true,
'hover-text-primary hover-cursor-pointer': !this.disabled,
'flex-auto leading-m font-medium tracking-wide text-m rounded-s transition-colors': true,
'text-primary hover-underline hover-cursor-pointer': !this.disabled,
'focus-outline-none focus-ring-2 ring-primary-50 ring-offset-2': !this.disabled,
'text-disabled cursor-default': this.disabled,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,17 @@ export class InternalCustomerPortalPasswordResetView extends TranslatableMixin(I
this.edit({ password_old: this.passwordOld ?? '' });
super.submit();
}

protected async _fetch<TResult = Data>(...args: Parameters<Window['fetch']>): Promise<TResult> {
const request = new Request(...args);
if (request.method !== 'PATCH') return super._fetch<TResult>(...args);

const body = await request.json();
const data = await super._fetch<Data>(...args);

data.password_old = body.password_old;
data.password = body.password;

return data as unknown as TResult;
}
}
Loading
Loading