Skip to content

Commit

Permalink
Version 1.1.0
Browse files Browse the repository at this point in the history
Merge pull request #41 from Freemius/develop
  • Loading branch information
swashata authored Nov 26, 2024
2 parents 374c2d6 + a1d1c19 commit 1ef8a45
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 27 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,31 @@ an unexpected way, you can use this:
## How to setup the development environment for contributions

Please our [Contributors Guide](CONTRIBUTING.md).

## Filters

- `pricing/show_annual_in_monthly` - Set the value to `false` to make the annual
pricing display number in annual cycle (instead of monthly cycle).
- `plugin_icon` - See
[documentation](https://freemius.com/help/documentation/wordpress-sdk/opt-in-message/#opt_in_icon_customization),
the same filter is used for the pricing page.
- `pricing/disable_single_package` - Set the value to `true` to disable the
enhanced appearance of the single package plan, where every pricing takes a
new column.
- `pricing/css_path` - Set the value to the path of your custom CSS file to
override the default CSS. The path should be absolute (just like the
`plugin_icon` or the `freemius_pricing_js_path` filters).

### Adding custom CSS in your Plugin

Set the custom CSS path using the `pricing/css_path` filter:

```php
<?php
function my_custom_pricing_css_path( $default_pricing_css_path ) {
return plugin_dir_path( __FILE__ ) .
'/path/to/your/freemius-pricing.css';
}

my_fs()->add_filter( 'pricing/css_path', 'my_custom_pricing_css_path' );
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "freemius-pricing-page",
"version": "1.0.0",
"version": "1.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.30",
Expand Down
9 changes: 5 additions & 4 deletions src/components/FreemiusPricingMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class FreemiusPricingMain extends Component {
selectedLicenseQuantity: this.getDefaultLicenseQuantity(),
upgradingToPlanID: null,
license: FSConfig.license,
showAnnualInMonthly: FSConfig.show_annual_in_monthly,
};

this.changeBillingCycle = this.changeBillingCycle.bind(this);
Expand Down Expand Up @@ -186,7 +187,7 @@ class FreemiusPricingMain extends Component {

return (
<object
data={this.state.plugin.icon}
data={FSConfig.plugin_icon ?? this.state.plugin.icon}
className="fs-plugin-logo"
type="image/png"
>
Expand Down Expand Up @@ -586,15 +587,15 @@ class FreemiusPricingMain extends Component {

let pricing = pricingCollection[pricingIndex];

if (null != pricing.monthly_price) {
if (null != pricing.monthly_price && !pricing.is_hidden) {
billingCycles[BillingCycleString.MONTHLY] = true;
}

if (null != pricing.annual_price) {
if (null != pricing.annual_price && !pricing.is_hidden) {
billingCycles[BillingCycleString.ANNUAL] = true;
}

if (null != pricing.lifetime_price) {
if (null != pricing.lifetime_price && !pricing.is_hidden) {
billingCycles[BillingCycleString.LIFETIME] = true;
}

Expand Down
100 changes: 79 additions & 21 deletions src/components/Package/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,27 @@ class Package extends Component {
return 'upgrade';
}

if (PlanManager.getInstance().isFreePlan(contextPlan.pricing)) {
const isContextPricingFree = PlanManager.getInstance().isFreePlan(
contextPlan.pricing
);
const isPlanPricingFree = PlanManager.getInstance().isFreePlan(
plan.pricing
);

// There are some cases where we will show the Free plan, especially if we are on free plan.
// For example, there's only one plan of the product and the plan doesn't have multiple pricings.
if (isContextPricingFree && isPlanPricingFree) {
return 'none';
}

if (isContextPricingFree) {
return 'upgrade';
}

// At this point, the install has a plan. Now we need to compare the given plan with the context plan.

// If the given plan is free, then it is always a downgrade.
if (PlanManager.getInstance().isFreePlan(plan.pricing)) {
if (isPlanPricingFree) {
return 'downgrade';
}

Expand Down Expand Up @@ -174,7 +187,11 @@ class Package extends Component {
}
}

getUndiscountedPrice(planPackage, selectedPricing) {
getUndiscountedPrice(
planPackage,
selectedPricing,
selectedPricingCycleLabel
) {
if (
BillingCycleString.ANNUAL !== this.context.selectedBillingCycle ||
!(this.context.annualDiscount > 0)
Expand All @@ -186,15 +203,26 @@ class Package extends Component {
return <Placeholder className={'fs-undiscounted-price'} />;
}

let amount;

if ('mo' === selectedPricingCycleLabel) {
amount = selectedPricing.getMonthlyAmount(
BillingCycle.MONTHLY,
true,
Package.locale
);
} else {
amount = selectedPricing.getYearlyAmount(
BillingCycle.MONTHLY,
true,
Package.locale
);
}

return (
<div className="fs-undiscounted-price">
Normally {this.context.currencySymbols[this.context.selectedCurrency]}
{selectedPricing.getMonthlyAmount(
BillingCycle.MONTHLY,
true,
Package.locale
)}{' '}
/ mo
{amount} / {selectedPricingCycleLabel}
</div>
);
}
Expand Down Expand Up @@ -264,7 +292,9 @@ class Package extends Component {
pricingCollection = {},
selectedPricing = null,
selectedPricingAmount = null,
supportLabel = null;
supportLabel = null,
showAnnualInMonthly = this.context.showAnnualInMonthly,
selectedPricingCycleLabel = 'mo';

if (this.props.isFirstPlanPackage) {
Package.contextInstallPlanFound = false;
Expand Down Expand Up @@ -298,15 +328,37 @@ class Package extends Component {

this.previouslySelectedPricingByPlan[planPackage.id] = selectedPricing;

selectedPricingAmount = (
BillingCycleString.ANNUAL === this.context.selectedBillingCycle
? // The 'en-US' is intentionally hard-coded here because we are spliting the decimal by '.'.
Helper.formatNumber(
selectedPricing.getMonthlyAmount(BillingCycle.ANNUAL),
'en-US'
)
: selectedPricing[`${this.context.selectedBillingCycle}_price`]
).toString();
if (BillingCycleString.ANNUAL === this.context.selectedBillingCycle) {
if (
true === showAnnualInMonthly ||
(Helper.isUndefinedOrNull(showAnnualInMonthly) &&
selectedPricing.hasMonthlyPrice())
) {
// The 'en-US' is intentionally hard-coded here because we are spliting the decimal by '.'.
selectedPricingAmount = Helper.formatNumber(
selectedPricing.getMonthlyAmount(BillingCycle.ANNUAL),
'en-US'
);
}

if (
false === showAnnualInMonthly ||
(Helper.isUndefinedOrNull(showAnnualInMonthly) &&
!selectedPricing.hasMonthlyPrice())
) {
// The 'en-US' is intentionally hard-coded here because we are spliting the decimal by '.'.
selectedPricingAmount = Helper.formatNumber(
selectedPricing.getYearlyAmount(BillingCycle.ANNUAL),
'en-US'
);
selectedPricingCycleLabel = 'yr';
}
} else {
selectedPricingAmount =
selectedPricing[
`${this.context.selectedBillingCycle}_price`
].toString();
}
}

if (!planPackage.hasAnySupport()) {
Expand Down Expand Up @@ -390,7 +442,11 @@ class Package extends Component {
<h3 className="fs-plan-description">
<strong>{planPackage.description_lines}</strong>
</h3>
{this.getUndiscountedPrice(planPackage, selectedPricing)}
{this.getUndiscountedPrice(
planPackage,
selectedPricing,
selectedPricingCycleLabel
)}
<div className="fs-selected-pricing-amount">
<strong className="fs-currency-symbol">
{!planPackage.is_free_plan
Expand All @@ -411,7 +467,9 @@ class Package extends Component {
{!planPackage.is_free_plan &&
BillingCycleString.LIFETIME !==
this.context.selectedBillingCycle && (
<sub className="fs-selected-pricing-amount-cycle">/ mo</sub>
<sub className="fs-selected-pricing-amount-cycle">
/ {selectedPricingCycleLabel}
</sub>
)}
</span>
</div>
Expand Down
7 changes: 6 additions & 1 deletion src/components/PackagesContainer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Placeholder from '../Placeholder';
import { debounce } from '../../utils/debounce';

import './style.scss';
import { FSConfig } from '../../index';

class PackagesContainer extends Component {
static contextType = FSPricingContext;
Expand Down Expand Up @@ -323,7 +324,11 @@ class PackagesContainer extends Component {
currentLicenseQuantities = {},
isSinglePlan = false;

if (this.context.paidPlansCount > 1 || 1 === licenseQuantitiesCount) {
if (
this.context.paidPlansCount > 1 ||
1 === licenseQuantitiesCount ||
true === FSConfig.disable_single_package
) {
// If there are more than one paid plans, create a package component for each plan.
packages = this.context.plans;
} else {
Expand Down
32 changes: 32 additions & 0 deletions src/entities/Pricing.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,38 @@ export class Pricing {
return amount;
}

/**
* @param {int} billingCycle One of the following: 1, 12, 0 (for lifetime).
* @param {boolean} [format] If true, the number 1299 for example will become 1,299.
* @param {string} [locale] The country code and language code combination (e.g. 'fr-FR').
*
* @return {string|number}
*/
getYearlyAmount(billingCycle, format, locale) {
let amount = 0.0;

switch (billingCycle) {
case BillingCycle.MONTHLY:
amount = this.hasMonthlyPrice()
? this.monthly_price * 12
: this.annual_price;
break;
case BillingCycle.ANNUAL:
amount = this.hasAnnualPrice()
? this.annual_price
: this.monthly_price * 12;
break;
}

amount = parseFloat(amount);

if (format) {
amount = Helper.formatNumber(amount, locale);
}

return amount;
}

getLicenses() {
return this.isUnlimited() ? UnlimitedLicenses : this.licenses;
}
Expand Down

0 comments on commit 1ef8a45

Please sign in to comment.