Add new plugin files.
This gets the plugin running again without name collisions. A solid starting point
This commit is contained in:
@@ -1 +0,0 @@
|
||||
export default Ember.Component.extend({});
|
||||
@@ -1,5 +0,0 @@
|
||||
export default Ember.Component.extend({
|
||||
classNames: "donation-list",
|
||||
hasSubscriptions: Ember.computed.notEmpty("subscriptions"),
|
||||
hasCharges: Ember.computed.notEmpty("charges")
|
||||
});
|
||||
@@ -1,99 +0,0 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { formatAnchor, formatAmount } from "../lib/donation-utilities";
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNameBindings: [":donation-row", "canceled", "updating"],
|
||||
includePrefix: Ember.computed.or("invoice", "charge"),
|
||||
canceled: Ember.computed.equal("subscription.status", "canceled"),
|
||||
|
||||
@computed("subscription", "invoice", "charge", "customer")
|
||||
data(subscription, invoice, charge, customer) {
|
||||
if (subscription) {
|
||||
return $.extend({}, subscription.plan, {
|
||||
anchor: subscription.billing_cycle_anchor
|
||||
});
|
||||
} else if (invoice) {
|
||||
let receiptSent = false;
|
||||
|
||||
if (invoice.receipt_number && customer.email) {
|
||||
receiptSent = true;
|
||||
}
|
||||
|
||||
return $.extend({}, invoice.lines.data[0], {
|
||||
anchor: invoice.date,
|
||||
invoiceLink: invoice.invoice_pdf,
|
||||
receiptSent
|
||||
});
|
||||
} else if (charge) {
|
||||
let receiptSent = false;
|
||||
|
||||
if (charge.receipt_number && charge.receipt_email) {
|
||||
receiptSent = true;
|
||||
}
|
||||
|
||||
return $.extend({}, charge, {
|
||||
anchor: charge.created,
|
||||
receiptSent
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@computed("data.currency")
|
||||
currency(currency) {
|
||||
return currency ? currency.toUpperCase() : null;
|
||||
},
|
||||
|
||||
@computed("data.amount", "currency")
|
||||
amount(amount, currency) {
|
||||
return formatAmount(amount, currency);
|
||||
},
|
||||
|
||||
@computed("data.interval")
|
||||
interval(interval) {
|
||||
return interval || "once";
|
||||
},
|
||||
|
||||
@computed("data.anchor", "interval")
|
||||
period(anchor, interval) {
|
||||
return I18n.t(`discourse_donations.period.${interval}`, {
|
||||
anchor: formatAnchor(interval, moment.unix(anchor))
|
||||
});
|
||||
},
|
||||
|
||||
cancelSubscription() {
|
||||
const subscriptionId = this.get("subscription.id");
|
||||
this.set("updating", true);
|
||||
|
||||
ajax("/donate/charges/cancel-subscription", {
|
||||
data: {
|
||||
subscription_id: subscriptionId
|
||||
},
|
||||
method: "put"
|
||||
})
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
this.set("subscription", result.subscription);
|
||||
}
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => {
|
||||
this.set("updating", false);
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
cancelSubscription() {
|
||||
showModal("cancel-subscription", {
|
||||
model: {
|
||||
currency: this.get("currency"),
|
||||
amount: this.get("amount"),
|
||||
period: this.get("period"),
|
||||
confirm: () => this.cancelSubscription()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,286 +0,0 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { formatAnchor, zeroDecimalCurrencies } from "../lib/donation-utilities";
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import { emailValid as emailValidHelper } from "discourse/lib/utilities";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
result: [],
|
||||
stripe: null,
|
||||
transactionInProgress: null,
|
||||
settings: null,
|
||||
showTransactionFeeDescription: false,
|
||||
includeTransactionFee: true,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
const user = this.get("currentUser");
|
||||
const settings = Discourse.SiteSettings;
|
||||
|
||||
this.setProperties({
|
||||
create_accounts:
|
||||
!user && settings.discourse_donations_enable_create_accounts,
|
||||
stripe: Stripe(settings.discourse_donations_public_key),
|
||||
color: jQuery("body").css("color")
|
||||
});
|
||||
|
||||
const types = settings.discourse_donations_types.split("|") || [];
|
||||
const amounts = this.get("donateAmounts");
|
||||
|
||||
this.setProperties({
|
||||
types,
|
||||
type: types[0],
|
||||
amount: amounts[0].value
|
||||
});
|
||||
},
|
||||
|
||||
@computed
|
||||
causes() {
|
||||
const categoryEnabled =
|
||||
Discourse.SiteSettings.discourse_donations_cause_category;
|
||||
|
||||
if (categoryEnabled) {
|
||||
let categoryIds = Discourse.SiteSettings.discourse_donations_causes_categories.split(
|
||||
"|"
|
||||
);
|
||||
|
||||
if (categoryIds.length) {
|
||||
categoryIds = categoryIds.map(Number);
|
||||
return this.site
|
||||
.get("categoriesList")
|
||||
.filter(c => {
|
||||
return categoryIds.indexOf(c.id) > -1;
|
||||
})
|
||||
.map(c => {
|
||||
return {
|
||||
id: c.id,
|
||||
name: c.name
|
||||
};
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
const causes = Discourse.SiteSettings.discourse_donations_causes;
|
||||
return causes ? causes.split("|") : [];
|
||||
}
|
||||
},
|
||||
|
||||
@computed("types")
|
||||
donationTypes(types) {
|
||||
return types.map(type => {
|
||||
return {
|
||||
id: type,
|
||||
name: I18n.t(`discourse_donations.types.${type}`)
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@computed("type")
|
||||
period(type) {
|
||||
return I18n.t(`discourse_donations.period.${type}`, {
|
||||
anchor: formatAnchor(type)
|
||||
});
|
||||
},
|
||||
|
||||
@computed
|
||||
donateAmounts() {
|
||||
const setting = Discourse.SiteSettings.discourse_donations_amounts.split(
|
||||
"|"
|
||||
);
|
||||
if (setting.length) {
|
||||
return setting.map(amount => {
|
||||
return {
|
||||
value: parseInt(amount, 10),
|
||||
name: `${amount}.00`
|
||||
};
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
@computed("stripe")
|
||||
card(stripe) {
|
||||
const color = this.get("color");
|
||||
const hidePostalCode = !Discourse.SiteSettings.discourse_donations_zip_code;
|
||||
const elements = stripe.elements();
|
||||
|
||||
const style = {
|
||||
base: {
|
||||
color,
|
||||
iconColor: color,
|
||||
"::placeholder": { color }
|
||||
}
|
||||
};
|
||||
|
||||
const card = elements.create("card", { style, hidePostalCode });
|
||||
|
||||
card.addEventListener("change", event => {
|
||||
if (event.error) {
|
||||
this.set("stripeError", event.error.message);
|
||||
} else {
|
||||
this.set("stripeError", "");
|
||||
}
|
||||
|
||||
if (event.elementType === "card" && event.complete) {
|
||||
this.set("stripeReady", true);
|
||||
}
|
||||
});
|
||||
|
||||
return card;
|
||||
},
|
||||
|
||||
@computed("amount")
|
||||
transactionFee(amount) {
|
||||
const fixed =
|
||||
Discourse.SiteSettings.discourse_donations_transaction_fee_fixed;
|
||||
const percent =
|
||||
Discourse.SiteSettings.discourse_donations_transaction_fee_percent;
|
||||
const fee = (amount + fixed) / (1 - percent) - amount;
|
||||
return Math.round(fee * 100) / 100;
|
||||
},
|
||||
|
||||
@computed("amount", "transactionFee", "includeTransactionFee")
|
||||
totalAmount(amount, fee, include) {
|
||||
if (include) return amount + fee;
|
||||
return amount;
|
||||
},
|
||||
|
||||
@computed("email")
|
||||
emailValid(email) {
|
||||
return emailValidHelper(email);
|
||||
},
|
||||
|
||||
@computed("email", "emailValid")
|
||||
showEmailError(email, emailValid) {
|
||||
return email && email.length > 3 && !emailValid;
|
||||
},
|
||||
|
||||
@computed("currentUser", "emailValid")
|
||||
userReady(currentUser, emailValid) {
|
||||
return currentUser || emailValid;
|
||||
},
|
||||
|
||||
@computed("cause")
|
||||
causeValid(cause) {
|
||||
return cause || !Discourse.SiteSettings.discourse_donations_cause_required;
|
||||
},
|
||||
|
||||
@computed("userReady", "stripeReady", "causeValid")
|
||||
formIncomplete(userReady, stripeReady, causeValid) {
|
||||
return !userReady || !stripeReady || !causeValid;
|
||||
},
|
||||
|
||||
@computed("transactionInProgress", "formIncomplete")
|
||||
disableSubmit(transactionInProgress, formIncomplete) {
|
||||
return transactionInProgress || formIncomplete;
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
this.get("card").mount("#card-element");
|
||||
jQuery(document).on("click", Ember.run.bind(this, this.documentClick));
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
jQuery(document).off("click", Ember.run.bind(this, this.documentClick));
|
||||
},
|
||||
|
||||
documentClick(e) {
|
||||
let $element = jQuery(".transaction-fee-description");
|
||||
let $target = jQuery(e.target);
|
||||
if ($target.closest($element).length < 1 && this._state !== "destroying") {
|
||||
this.set("showTransactionFeeDescription", false);
|
||||
}
|
||||
},
|
||||
|
||||
setSuccess() {
|
||||
this.set("paymentSuccess", true);
|
||||
},
|
||||
|
||||
endTranscation() {
|
||||
this.set("transactionInProgress", false);
|
||||
},
|
||||
|
||||
concatMessages(messages) {
|
||||
this.set("result", this.get("result").concat(messages));
|
||||
},
|
||||
|
||||
actions: {
|
||||
toggleTransactionFeeDescription() {
|
||||
this.toggleProperty("showTransactionFeeDescription");
|
||||
},
|
||||
|
||||
submitStripeCard() {
|
||||
let self = this;
|
||||
this.set("transactionInProgress", true);
|
||||
|
||||
this.get("stripe")
|
||||
.createToken(this.get("card"))
|
||||
.then(data => {
|
||||
self.set("result", []);
|
||||
|
||||
if (data.error) {
|
||||
this.setProperties({
|
||||
stripeError: data.error.message,
|
||||
stripeReady: false
|
||||
});
|
||||
self.endTranscation();
|
||||
} else {
|
||||
const settings = Discourse.SiteSettings;
|
||||
|
||||
const transactionFeeEnabled =
|
||||
settings.discourse_donations_enable_transaction_fee;
|
||||
let amount = transactionFeeEnabled
|
||||
? this.get("totalAmount")
|
||||
: this.get("amount");
|
||||
|
||||
if (
|
||||
zeroDecimalCurrencies.indexOf(
|
||||
settings.discourse_donations_currency
|
||||
) === -1
|
||||
) {
|
||||
amount = amount * 100;
|
||||
}
|
||||
|
||||
let params = {
|
||||
stripeToken: data.token.id,
|
||||
cause: self.get("cause"),
|
||||
type: self.get("type"),
|
||||
amount,
|
||||
email: self.get("email"),
|
||||
username: self.get("username"),
|
||||
create_account: self.get("create_accounts")
|
||||
};
|
||||
|
||||
if (!self.get("paymentSuccess")) {
|
||||
ajax("/donate/charges", {
|
||||
data: params,
|
||||
method: "post"
|
||||
}).then(result => {
|
||||
if (result.subscription) {
|
||||
let subscription = $.extend({}, result.subscription, {
|
||||
new: true
|
||||
});
|
||||
this.get("subscriptions").unshiftObject(subscription);
|
||||
}
|
||||
|
||||
if (result.charge) {
|
||||
let charge = $.extend({}, result.charge, {
|
||||
new: true
|
||||
});
|
||||
this.get("charges").unshiftObject(charge);
|
||||
}
|
||||
|
||||
self.concatMessages(result.messages);
|
||||
|
||||
self.endTranscation();
|
||||
self.onCompleteTransation();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
{{#if siteSettings.discourse_donations_cause_category}}
|
||||
{{mount-widget widget="category-header-widget" args=(hash currentPath=currentPath)}}
|
||||
{{/if}}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
{{#if siteSettings.discourse_donations_cause_category}}
|
||||
<section class='field'>
|
||||
{{input type="checkbox" checked=category.custom_fields.donations_show_amounts}}
|
||||
<span>{{i18n 'discourse_donations.cause.amounts.setting_label'}}</span>
|
||||
</section>
|
||||
|
||||
<section class='field'>
|
||||
<label>{{i18n 'discourse_donations.cause.github.setting_label'}}</label>
|
||||
{{text-field value=category.custom_fields.donations_github placeholderKey="discourse_donations.cause.github.setting_placeholder"}}
|
||||
</section>
|
||||
|
||||
<section class='field'>
|
||||
<label>{{i18n 'discourse_donations.cause.meta.setting_label'}}</label>
|
||||
{{text-field value=category.custom_fields.donations_meta placeholderKey="discourse_donations.cause.meta.setting_placeholder"}}
|
||||
</section>
|
||||
|
||||
<section class='field'>
|
||||
<label>{{i18n 'discourse_donations.cause.maintainers.label'}}</label>
|
||||
{{user-selector usernames=category.custom_fields.donations_maintainers}}
|
||||
</section>
|
||||
|
||||
<section class='field'>
|
||||
<label>{{i18n 'discourse_donations.cause.maintainers.setting_label'}}</label>
|
||||
{{input value=category.custom_fields.donations_maintainers_label}}
|
||||
</section>
|
||||
|
||||
<section class='field'>
|
||||
<label>{{i18n 'discourse_donations.cause.release_latest.label'}}</label>
|
||||
{{input value=category.custom_fields.donations_release_latest}}
|
||||
</section>
|
||||
|
||||
<section class='field'>
|
||||
<label>{{i18n 'discourse_donations.cause.release_oldest.label'}}</label>
|
||||
{{input value=category.custom_fields.donations_release_oldest}}
|
||||
</section>
|
||||
{{/if}}
|
||||
@@ -1,5 +0,0 @@
|
||||
{{#if siteSettings.discourse_donations_enabled}}
|
||||
<a href="/donate">
|
||||
{{i18n 'discourse_donations.nav_item'}}
|
||||
</a>
|
||||
{{/if}}
|
||||
@@ -1,12 +0,0 @@
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
confirm() {
|
||||
this.get("model.confirm")();
|
||||
this.send("closeModal");
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.send("closeModal");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,61 +0,0 @@
|
||||
import { default as computed } from "ember-addons/ember-computed-decorators";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import { emailValid } from "discourse/lib/utilities";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
loadingDonations: false,
|
||||
loadDonationsDisabled: Ember.computed.not("emailVaild"),
|
||||
|
||||
@computed("charges.[]", "subscriptions.[]")
|
||||
hasDonations(charges, subscriptions) {
|
||||
return (
|
||||
(charges && charges.length > 0) ||
|
||||
(subscriptions && subscriptions.length > 0)
|
||||
);
|
||||
},
|
||||
|
||||
@computed("email")
|
||||
emailVaild(email) {
|
||||
return emailValid(email);
|
||||
},
|
||||
|
||||
actions: {
|
||||
stripeTransationCompleteCtr() {},
|
||||
|
||||
loadDonations() {
|
||||
let email = this.get("email");
|
||||
|
||||
this.set("loadingDonations", true);
|
||||
|
||||
ajax("/donate/charges", {
|
||||
data: { email },
|
||||
type: "GET"
|
||||
})
|
||||
.then(result => {
|
||||
this.setProperties({
|
||||
charges: Ember.A(result.charges),
|
||||
subscriptions: Ember.A(result.subscriptions),
|
||||
customer: result.customer
|
||||
});
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => {
|
||||
this.setProperties({
|
||||
loadingDonations: false,
|
||||
hasEmailResult: true
|
||||
});
|
||||
|
||||
Ember.run.later(() => {
|
||||
this.set("hasEmailResult", false);
|
||||
}, 6000);
|
||||
});
|
||||
},
|
||||
|
||||
showLogin() {
|
||||
const controller = getOwner(this).lookup("route:application");
|
||||
controller.send("showLogin");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
export default function() {
|
||||
const { disabled_plugins = [] } = this.site;
|
||||
|
||||
if (disabled_plugins.indexOf("discourse-patrons") !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.route("patrons", function() {
|
||||
this.route("show", { path: ":payment_id" });
|
||||
});
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export default function() {
|
||||
this.route("donate");
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
|
||||
export default {
|
||||
name: "donations-edits",
|
||||
initialize(container) {
|
||||
const siteSettings = container.lookup("site-settings:main");
|
||||
|
||||
withPluginApi("0.8.12", api => {
|
||||
api.decorateCooked(
|
||||
$post => {
|
||||
const $form = $post.find(".stripe-checkout");
|
||||
if ($form.length) {
|
||||
const $input = $form.find("input");
|
||||
var s = document.createElement("script");
|
||||
s.src = "https://checkout.stripe.com/checkout.js";
|
||||
s.setAttribute("class", "stripe-button");
|
||||
s.setAttribute(
|
||||
"data-key",
|
||||
siteSettings.discourse_donations_public_key
|
||||
);
|
||||
s.setAttribute("data-amount", $input.attr("amount"));
|
||||
s.setAttribute(
|
||||
"data-name",
|
||||
siteSettings.discourse_donations_shop_name
|
||||
);
|
||||
s.setAttribute("data-description", $form.attr("content"));
|
||||
s.setAttribute("data-image", $form.attr("image") || "");
|
||||
s.setAttribute("data-locale", "auto");
|
||||
s.setAttribute(
|
||||
"data-zip-code",
|
||||
siteSettings.discourse_donations_zip_code
|
||||
);
|
||||
s.setAttribute(
|
||||
"data-billing-address",
|
||||
siteSettings.discourse_donations_billing_address
|
||||
);
|
||||
s.setAttribute(
|
||||
"data-currency",
|
||||
siteSettings.discourse_donations_currency
|
||||
);
|
||||
$form.append(s);
|
||||
}
|
||||
},
|
||||
{ id: "discourse-donations" }
|
||||
);
|
||||
|
||||
if (siteSettings.discourse_donations_cause_category) {
|
||||
api.decorateWidget("category-header-widget:after", helper => {
|
||||
helper.widget.appEvents.on("page:changed", () => {
|
||||
helper.widget.scheduleRerender();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
const formatAnchor = function(type = null, time = moment()) {
|
||||
let format;
|
||||
|
||||
switch (type) {
|
||||
case "once":
|
||||
format = "Do MMMM YYYY";
|
||||
break;
|
||||
case "week":
|
||||
format = "dddd";
|
||||
break;
|
||||
case "month":
|
||||
format = "Do";
|
||||
break;
|
||||
case "year":
|
||||
format = "MMMM D";
|
||||
break;
|
||||
default:
|
||||
format = "dddd";
|
||||
}
|
||||
|
||||
return moment(time).format(format);
|
||||
};
|
||||
|
||||
const zeroDecimalCurrencies = [
|
||||
"MGA",
|
||||
"BIF",
|
||||
"CLP",
|
||||
"PYG",
|
||||
"DFJ",
|
||||
"RWF",
|
||||
"GNF",
|
||||
"UGX",
|
||||
"JPY",
|
||||
"VND",
|
||||
"VUV",
|
||||
"XAF",
|
||||
"KMF",
|
||||
"KRW",
|
||||
"XOF",
|
||||
"XPF"
|
||||
];
|
||||
|
||||
const formatAmount = function(amount, currency) {
|
||||
let zeroDecimal = zeroDecimalCurrencies.indexOf(currency) > -1;
|
||||
return zeroDecimal ? amount : (amount / 100).toFixed(2);
|
||||
};
|
||||
|
||||
export { formatAnchor, formatAmount, zeroDecimalCurrencies };
|
||||
@@ -1,40 +0,0 @@
|
||||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
redirect() {
|
||||
if (!Discourse.SiteSettings.discourse_donations_enabled) {
|
||||
DiscourseURL.routeTo("/");
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
setupController(controller) {
|
||||
let charges = [];
|
||||
let subscriptions = [];
|
||||
let customer = {};
|
||||
|
||||
controller.set("loadingDonations", true);
|
||||
|
||||
ajax("/donate/charges")
|
||||
.then(result => {
|
||||
if (result) {
|
||||
charges = result.charges;
|
||||
subscriptions = result.subscriptions;
|
||||
customer = result.customer;
|
||||
}
|
||||
|
||||
controller.setProperties({
|
||||
charges: Ember.A(charges),
|
||||
subscriptions: Ember.A(subscriptions),
|
||||
customer
|
||||
});
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => {
|
||||
controller.set("loadingDonations", false);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
<form id="payment-form" class="form-horizontal">
|
||||
<div class="donations-page-payment">
|
||||
{{stripe-card
|
||||
charges=charges
|
||||
subscriptions=subscriptions
|
||||
onCompleteTransation=onCompleteTransation
|
||||
}}
|
||||
</div>
|
||||
</form>
|
||||
@@ -1,28 +0,0 @@
|
||||
{{#if hasSubscriptions}}
|
||||
<div class="subscription-list">
|
||||
<div class="underline">{{i18n 'discourse_donations.donations.subscriptions'}}</div>
|
||||
<ul>
|
||||
{{#each subscriptions as |s|}}
|
||||
<li>{{donation-row subscription=s.subscription customer=customer new=s.new}}</li>
|
||||
{{#if s.invoices}}
|
||||
<ul>
|
||||
{{#each s.invoices as |invoice|}}
|
||||
<li>{{donation-row invoice=invoice customer=customer new=s.new}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if hasCharges}}
|
||||
<div class="charge-list">
|
||||
<div class='underline'>{{i18n 'discourse_donations.donations.charges'}}</div>
|
||||
<ul>
|
||||
{{#each charges as |charge|}}
|
||||
<li>{{donation-row charge=charge customer=customer new=charge.new}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
@@ -1,41 +0,0 @@
|
||||
{{#if includePrefix}}
|
||||
<span>{{i18n 'discourse_donations.invoice_prefix'}}</span>
|
||||
{{/if}}
|
||||
|
||||
<span class="donation-row-currency">{{currency}}</span>
|
||||
|
||||
<span class="donation-row-amount">{{amount}}</span>
|
||||
|
||||
<span class="donation-row-period">{{period}}</span>
|
||||
|
||||
{{#if invoice}}
|
||||
<a href='{{data.invoiceLink}}' target='_blank'>({{i18n 'discourse_donations.invoice'}})</a>
|
||||
{{/if}}
|
||||
|
||||
{{#if currentUser}}
|
||||
{{#if subscription}}
|
||||
<span class="donation-row-subscription">
|
||||
{{#if updating}}
|
||||
{{loading-spinner size='small'}}
|
||||
{{else}}
|
||||
{{#unless canceled}}
|
||||
<a {{action 'cancelSubscription'}}>
|
||||
{{i18n 'cancel'}}
|
||||
</a>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if receiptSent}}
|
||||
<span>–</span>
|
||||
<span>{{i18n 'discourse_donations.receipt' email=customer.email}}</span>
|
||||
{{/if}}
|
||||
|
||||
{{#if new}}
|
||||
<span class="new-flag">
|
||||
{{d-icon 'circle'}}
|
||||
<span>{{i18n 'new_item'}}</span>
|
||||
</span>
|
||||
{{/if}}
|
||||
@@ -1,118 +0,0 @@
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
{{i18n 'discourse_donations.type'}}
|
||||
</label>
|
||||
<div class="controls controls-dropdown">
|
||||
{{combo-box content=donationTypes value=type}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="card-element">
|
||||
{{i18n 'discourse_donations.amount'}}
|
||||
{{siteSettings.discourse_donations_currency}}
|
||||
</label>
|
||||
<div class="controls controls-dropdown">
|
||||
{{combo-box valueAttribute="value" content=donateAmounts value=amount}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if siteSettings.discourse_donations_enable_transaction_fee}}
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
{{input type="checkbox" checked=includeTransactionFee}}
|
||||
<span>{{i18n 'discourse_donations.transaction_fee.label' transactionFee=transactionFee currency=siteSettings.discourse_donations_currency}}</span>
|
||||
<div class='transaction-fee-description' {{action 'toggleTransactionFeeDescription'}}>
|
||||
{{d-icon 'info-circle'}}
|
||||
{{#if showTransactionFeeDescription}}
|
||||
<div class="transaction-fee-description-modal">
|
||||
{{i18n 'discourse_donations.transaction_fee.description'}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class='control-label'>
|
||||
{{i18n 'discourse_donations.transaction_fee.total'}}
|
||||
</label>
|
||||
<div class="controls">
|
||||
{{siteSettings.discourse_donations_currency}}
|
||||
{{totalAmount}}
|
||||
{{period}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="control-group" style="width: 550px;">
|
||||
<label class="control-label" for="card-element">{{i18n 'discourse_donations.card'}}</label>
|
||||
<div class="controls">
|
||||
<div id="card-element"></div>
|
||||
{{#if stripeError}}
|
||||
<div class="stripe-error">{{stripeError}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#unless currentUser}}
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="card-element">{{i18n 'user.email.title'}}</label>
|
||||
<div class="controls">
|
||||
{{text-field value=email}}
|
||||
{{#if showEmailError}}
|
||||
<div class="error">{{i18n 'user.email.invalid'}}</div>
|
||||
{{else}}
|
||||
<div class="instructions">{{i18n 'discourse_donations.email_instructions'}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if create_accounts}}
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="card-element">{{i18n 'user.username.title'}}</label>
|
||||
<div class="controls">
|
||||
{{text-field value=username}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="card-element">{{i18n 'user.name.title'}}</label>
|
||||
<div class="controls">
|
||||
{{text-field value=name}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="card-element">{{i18n 'user.password.title'}}</label>
|
||||
<div class="controls">
|
||||
{{input type="password" value=password}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="control-group save-button">
|
||||
<div class="controls">
|
||||
|
||||
{{#d-button action="submitStripeCard" class="btn btn-primary btn-payment"}}
|
||||
{{#if create_accounts}}
|
||||
{{i18n 'discourse_donations.submit_with_create_account'}}
|
||||
{{else}}
|
||||
{{i18n 'discourse_donations.submit'}}
|
||||
{{/if}}
|
||||
{{/d-button}}
|
||||
|
||||
{{#if transactionInProgress}}
|
||||
{{loading-spinner size="small"}}
|
||||
{{/if}}
|
||||
|
||||
{{#each result as |message|}}
|
||||
<p>{{{message}}}</p>
|
||||
{{/each}}
|
||||
|
||||
{{#if success}}
|
||||
<p>{{i18n 'discourse_donations.messages.success'}}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,40 +0,0 @@
|
||||
<h3>{{i18n 'discourse_donations.title' site_name=siteSettings.title}}</h3>
|
||||
|
||||
<div class="donations-page-description">
|
||||
{{cook-text siteSettings.discourse_donations_page_description}}
|
||||
</div>
|
||||
|
||||
<div class="donations-page-payment">
|
||||
{{donation-form
|
||||
charges=charges
|
||||
subscriptions=subscriptions
|
||||
onCompleteTransation=(action "stripeTransationCompleteCtr")
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="donations-page-donations">
|
||||
<h3>{{i18n 'discourse_donations.donations.title'}}</h3>
|
||||
{{#if loadingDonations}}
|
||||
<span>{{i18n 'discourse_donations.donations.loading'}}</span>
|
||||
{{loading-spinner size='small'}}
|
||||
{{else}}
|
||||
{{#if currentUser}}
|
||||
{{#if hasDonations}}
|
||||
{{donation-list charges=charges subscriptions=subscriptions customer=customer}}
|
||||
{{else}}
|
||||
{{i18n 'discourse_donations.donations.none'}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if hasDonations}}
|
||||
{{donation-list charges=charges subscriptions=subscriptions customer=customer}}
|
||||
{{else}}
|
||||
{{#if hasEmailResult}}
|
||||
{{i18n 'discourse_donations.donations.none_email' email=email}}
|
||||
{{else}}
|
||||
{{input value=email placeholder=(i18n 'email')}}
|
||||
{{d-button action='loadDonations' label='discourse_donations.donations.load' disabled=loadDonationsDisabled}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
@@ -1,11 +0,0 @@
|
||||
{{#d-modal-body title='discourse_donations.subscription.cancel.title'}}
|
||||
{{i18n 'discourse_donations.subscription.cancel.description' site=siteSettings.title
|
||||
currency=model.currency
|
||||
amount=model.amount
|
||||
period=model.period}}
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
{{d-button action='confirm' label='yes_value' class='btn-primary'}}
|
||||
{{d-button action='cancel' label='no_value'}}
|
||||
</div>
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
index
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
show
|
||||
@@ -1,196 +0,0 @@
|
||||
import { createWidget } from "discourse/widgets/widget";
|
||||
import { h } from "virtual-dom";
|
||||
import { avatarFor } from "discourse/widgets/post";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
|
||||
function donationDisplay(amount, type) {
|
||||
return h(`div.donations-${type}`, [
|
||||
h("span", I18n.t(`discourse_donations.cause.category.${type}`)),
|
||||
h("span", `$${(amount / 100).toFixed(2)}`)
|
||||
]);
|
||||
}
|
||||
|
||||
createWidget("category-header-widget", {
|
||||
tagName: "span",
|
||||
|
||||
html(args) {
|
||||
const controller = this.register.lookup("controller:navigation/category");
|
||||
const category = controller.get("category");
|
||||
|
||||
if (
|
||||
args.currentPath.toLowerCase().indexOf("category") > -1 &&
|
||||
category &&
|
||||
category.donations_cause
|
||||
) {
|
||||
$("body").addClass("donations-category");
|
||||
|
||||
let contents = [
|
||||
h("div.donations-category-contents", [
|
||||
h("h1", category.name),
|
||||
h("div.category-title-description", h("p", category.description_text))
|
||||
])
|
||||
];
|
||||
|
||||
let metadata = [];
|
||||
|
||||
if (category.donations_total !== undefined) {
|
||||
metadata.push(donationDisplay(category.donations_total || 0, "total"));
|
||||
|
||||
if (Discourse.SiteSettings.discourse_donations_cause_month) {
|
||||
metadata.push(
|
||||
donationDisplay(category.donations_month || 0, "month")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (category.donations_github) {
|
||||
metadata.push(
|
||||
h(
|
||||
"div.donations-github",
|
||||
this.attach("link", {
|
||||
icon: "github",
|
||||
label: "discourse_donations.cause.github.label",
|
||||
href: category.donations_github
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (category.donations_meta) {
|
||||
metadata.push(
|
||||
h(
|
||||
"div.donations-meta",
|
||||
this.attach("link", {
|
||||
href: category.donations_meta,
|
||||
contents: () => {
|
||||
return [
|
||||
h("img.meta-icon", {
|
||||
attributes: {
|
||||
src:
|
||||
"https://discourse-meta.s3.dualstack.us-west-1.amazonaws.com/original/3X/b/1/b19ba793155a785bbd9707bc0cabbd3a987fa126.png?v=6"
|
||||
}
|
||||
}),
|
||||
h("span", I18n.t("discourse_donations.cause.meta.label"))
|
||||
];
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (category.donations_release_oldest) {
|
||||
let releaseArray = category.donations_release_oldest.split("/");
|
||||
let label = releaseArray[releaseArray.length - 1];
|
||||
metadata.push(
|
||||
h("div.donations-release-oldest", [
|
||||
h("span", ">="),
|
||||
this.attach("link", {
|
||||
href: category.donations_release_oldest,
|
||||
icon: "tag",
|
||||
rawLabel: label,
|
||||
omitSpan: true,
|
||||
attributes: {
|
||||
target: "_blank"
|
||||
}
|
||||
})
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if (category.donations_release_latest) {
|
||||
let releaseArray = category.donations_release_latest.split("/");
|
||||
let label = releaseArray[releaseArray.length - 1];
|
||||
metadata.push(
|
||||
h("div.donations-release-latest", [
|
||||
h("span", "<="),
|
||||
this.attach("link", {
|
||||
href: category.donations_release_latest,
|
||||
icon: "tag",
|
||||
rawLabel: label,
|
||||
omitSpan: true,
|
||||
attributes: {
|
||||
target: "_blank"
|
||||
}
|
||||
})
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if (metadata.length) {
|
||||
contents.push(h("div.donations-category-metadata", metadata));
|
||||
}
|
||||
|
||||
let users = [];
|
||||
|
||||
if (category.donations_backers.length) {
|
||||
users.push(
|
||||
h("div.donations-backers", [
|
||||
h(
|
||||
"div.donations-backers-title",
|
||||
I18n.t("discourse_donations.cause.backers.label")
|
||||
),
|
||||
category.donations_backers.map(user => {
|
||||
if (user) {
|
||||
return avatarFor("medium", {
|
||||
template: user.avatar_template,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
url: userPath(user.username),
|
||||
className: "backer-avatar"
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
})
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if (category.donations_maintainers.length) {
|
||||
let maintainersLabel =
|
||||
category.donations_maintainers_label ||
|
||||
I18n.t("discourse_donations.cause.maintainers.label");
|
||||
|
||||
users.push(
|
||||
h("div.donations-maintainers", [
|
||||
h("div.donations-maintainers-title", maintainersLabel),
|
||||
category.donations_maintainers.map(user => {
|
||||
if (user) {
|
||||
return avatarFor("medium", {
|
||||
template: user.avatar_template,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
url: userPath(user.username),
|
||||
className: "maintainer-avatar"
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
})
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if (users.length) {
|
||||
contents.push(h("div.donations-category-users", users));
|
||||
}
|
||||
|
||||
return h(
|
||||
"div.donations-category-header",
|
||||
{
|
||||
attributes: {
|
||||
style:
|
||||
"background-color: #" +
|
||||
category.color +
|
||||
"; color: #" +
|
||||
category.text_color +
|
||||
";"
|
||||
}
|
||||
},
|
||||
contents
|
||||
);
|
||||
} else {
|
||||
$("body").removeClass("donations-category");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,104 +0,0 @@
|
||||
function validationErrors(tagInfo, content, siteSettings) {
|
||||
let errors = [];
|
||||
if (!siteSettings.discourse_donations_public_key) {
|
||||
errors.push("missing key (site setting)");
|
||||
}
|
||||
if (!siteSettings.discourse_donations_currency) {
|
||||
errors.push("missing currency (site setting)");
|
||||
}
|
||||
if (!siteSettings.discourse_donations_shop_name) {
|
||||
errors.push("missing name (site setting)");
|
||||
}
|
||||
if (!siteSettings.discourse_donations_zip_code) {
|
||||
errors.push("missing zip code toggle (site setting)");
|
||||
}
|
||||
if (!siteSettings.discourse_donations_billing_address) {
|
||||
errors.push("missing billing address toggle (site setting)");
|
||||
}
|
||||
if (!tagInfo.attrs["amount"]) {
|
||||
errors.push("missing amount");
|
||||
}
|
||||
if (!content) {
|
||||
errors.push("missing description");
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
function replaceWithStripeOrError(siteSettings) {
|
||||
return function(state, tagInfo, content) {
|
||||
let errors = validationErrors(tagInfo, content, siteSettings);
|
||||
if (errors.length) {
|
||||
displayErrors(state, errors);
|
||||
} else {
|
||||
insertCheckout(state, tagInfo, content);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function displayErrors(state, errors) {
|
||||
let token = state.push("div-open", "div", 1);
|
||||
token.attrs = [["class", "stripe-errors"]];
|
||||
token = state.push("html_inline", "", 0);
|
||||
token.content = "Stripe checkout can't be rendered: " + errors.join(", ");
|
||||
state.push("div-close", "div", -1);
|
||||
}
|
||||
|
||||
function insertCheckout(state, tagInfo, content) {
|
||||
let token = state.push("stripe-checkout-form-open", "form", 1);
|
||||
token.attrs = [
|
||||
["method", "POST"],
|
||||
["action", "/checkout"],
|
||||
["content", content],
|
||||
["image", tagInfo.attrs["image"]],
|
||||
["class", "stripe-checkout"]
|
||||
];
|
||||
|
||||
token = state.push("stripe-checkout-form-amount", "input", 0);
|
||||
token.attrs = [
|
||||
["type", "hidden"],
|
||||
["name", "amount"],
|
||||
["value", tagInfo.attrs["amount"]]
|
||||
];
|
||||
|
||||
state.push("stripe-checkout-form-close", "form", -1);
|
||||
}
|
||||
|
||||
function setupMarkdownIt(helper, siteSettings) {
|
||||
helper.registerPlugin(md => {
|
||||
md.inline.bbcode.ruler.push("stripe-checkout", {
|
||||
tag: "stripe",
|
||||
replace: replaceWithStripeOrError(siteSettings)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function setup(helper) {
|
||||
helper.registerOptions((opts, siteSettings) => {
|
||||
helper.whiteList([
|
||||
"div[class]",
|
||||
"form[method]",
|
||||
"form[action]",
|
||||
"form[class]",
|
||||
"form[content]",
|
||||
"form[image]",
|
||||
"input[type]",
|
||||
"input[name]",
|
||||
"input[value]",
|
||||
"script[class]",
|
||||
"script[src]",
|
||||
"script[data-key]",
|
||||
"script[data-amount]",
|
||||
"script[data-name]",
|
||||
"script[data-description]",
|
||||
"script[data-image]",
|
||||
"script[data-zip-code]",
|
||||
"script[data-billing-address]",
|
||||
"script[data-currency]",
|
||||
"script[data-locale]"
|
||||
]);
|
||||
if (helper.markdownIt) {
|
||||
setupMarkdownIt(helper, siteSettings);
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user