Commit ac41e110 authored by Stephanie Kirtiadi's avatar Stephanie Kirtiadi
Browse files

Cryptocurrency page addition to Lektor site.

Ported from the donate site. Now redirects to
/donate-thank-you page (specified in the donate server)
until /cryptocurrency-thank-you page is built.

Issue #48280
parent bd882a55
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-copy"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
\ No newline at end of file
_model: donate-page
---
_template: layout.html
---
title: Cryptocurrency
---
section: Donate
---
section_id: donate
---
page_type: cryptocurrency
---
header_description:
---
header_description_alignment:
---
body:
---
html: cryptocurrency.html
......@@ -12,9 +12,9 @@ page_type: thank-you
---
header_description:
Thank you for your support of the Tor Project. You should receive an email receipt shortly. With your support, we'll be able to tackle ambitious projects, like increasing the capacity and scalability of the Tor network, taking our anti-censorship protections to the next level, and optimizing our development of Tor Browser for Android.
Thank you for standing up for privacy and freedom online. With your gift of cryptocurrency, you're helping the Tor Project give millions of people private access to the open web. Your contribution helps make Tor an even stronger tool against authoritarian governments and privacy-invading corporations.
It's an incredible time to stand up for world-leading security and privacy software. Tell family, friends, and colleagues that you're supporting privacy and security and taking back the internet with Tor!
For your convenience, our wallet addresses are listed below. Please make sure to copy the wallet addresses exactly when making your donation, as we are unable to recover funds sent to the wrong wallet.
<div class="content-center">
......
......@@ -4,7 +4,7 @@ frequency: both
---
default_frequency_for_both: single
---
section:
section:
---
section_id: donate
---
......@@ -14,7 +14,7 @@ _template: layout.html
---
html: donate-form.html
---
intro:
intro:
---
monthly_five: 10000
---
......
lego @ 49ec2baf
Subproject commit c889cd6f9ebe83056ef456061d8ece5183a66510
Subproject commit 49ec2baf84f0bfcdc1541c60a2cd15b8b491df7d
import React from 'react';
import {useState} from 'react';
import React, {useState} from 'react';
import {isFloat} from './number';
import {t} from './i18n';
......@@ -27,7 +26,7 @@ export function AmountField(props) {
return (
<div className="field-area currencyAmount">
<input className={classes.join(' ')} name={props.name} placeholder={props.placeHolder} maxLength="256" type="text" required onBlur={onCurrencyAmountBlur} />
<input className={classes.join(' ')} name={props.name} placeholder={props.placeHolder} maxLength="256" type="text" required onBlur={onCurrencyAmountBlur} />
{errorDiv}
</div>
);
......
import React, {useState, useEffect} from 'react';
import {Checkbox} from './checkbox';
import {WalletAddresses} from './wallet_addresses';
import {AmountField} from './amount_field';
import {t} from './i18n';
export function CryptocurrencyForm(props) {
const [donateAnonymously, setDonateAnonymously] = useState(false);
const [selectedCountry, setSelectedCountry] = useState('US');
const [fieldErrors, setFieldErrors] = useState([]);
const {wallets, donateProccessorBaseUrl} = props;
const countryChanged = (event) => {
setSelectedCountry(event.target.value);
};
const onAnonymousCheckboxChange = (event) => {
setDonateAnonymously(event.target.checked);
};
const onFieldValidate = (fieldName, valid) => {
if (valid) {
const pos = fieldErrors.indexOf(fieldName);
fieldErrors.splice(pos, 1);
setFieldErrors([...fieldErrors]);
} else {
setFieldErrors([fieldName, ...fieldErrors]);
}
};
const onSubmit = (event) => {
if (fieldErrors.length > 0) {
event.preventDefault();
}
};
const walletOptions = wallets.map((wallet) => {
return (<option key={wallet.symbol} value={wallet.symbol}>{wallet.name} ({wallet.symbol})</option>)
});
let conditionalFields = null;
if (!donateAnonymously) {
conditionalFields = (
<React.Fragment>
<input className="field" name="firstName" placeholder={t('t-first-name')} maxLength="256" type="text" required />
<input className="field" name="lastName" placeholder={t('t-last-name')} maxLength="256" type="text" />
</React.Fragment>
);
}
const requestDestination = donateProccessorBaseUrl + "/cryptocurrency/donate";
return(
<form action={requestDestination} method="POST" onSubmit={onSubmit}>
<div className="section">
<div className="form-column">
<h4>{t('t-your-info')}</h4>
<div className="form-fields">
<div className="anonymous-selection checkbox-row">
<Checkbox name="donateAnonymously" onChange={onAnonymousCheckboxChange} />
<label className="light" htmlFor="donateAnonymously">{t('t-donate-anonymously')}</label>
</div>
{conditionalFields}
<div className="mailing-list-opt-in checkbox-row">
<input name="mailingListOptIn" id="mailingListOptIn" type="checkbox" />
<label className="light" htmlFor="mailingListOptIn">{t('t-start-email-updates')}</label>
</div>
<input className="field" name="email" placeholder={t('t-email')} maxLength="256" type="text" required />
<label htmlFor="estimatedDonationDate">{t('t-estimated-donation-date')}</label>
<input name="estimatedDonationDate" id="estimatedDonationDate" placeholder={t('t-estimated-donation-date')} type="date" required />
<select className="field required" name="cryptocurrencyType" required>
<option value="">{t('t-choose-currency')}</option>
{walletOptions}
</select>
<AmountField name="currencyAmount" placeHolder={t('t-currency-amount')} onFieldValidate={onFieldValidate} />
</div>
</div>
<div className="wallet-column">
<h4>{t('t-wallet-addresses')}</h4>
<WalletAddresses wallets={wallets} />
</div>
</div>
<div className="section button-section">
<input className="donate button" type="submit" value={t('t-report-donation')}/>
</div>
</form>
);
}
......@@ -2,6 +2,7 @@ import 'babel-polyfill';
import {LoadingDialog} from './loading_dialog';
import {GivingForm} from './giving_form';
import {CampaignTotals} from './campaign_totals';
import {CryptocurrencyForm} from './cryptocurrency_form';
import React from 'react';
import ReactDOM from 'react-dom';
import {AppContext} from './app_context';
......@@ -11,7 +12,8 @@ const reactCallbacks = {};
const availableComponents = {
'LoadingDialog': LoadingDialog,
'GivingForm': GivingForm,
'CampaignTotals': CampaignTotals
'CampaignTotals': CampaignTotals,
'CryptocurrencyForm': CryptocurrencyForm,
};
const appContext = {};
......
import React, {useEffect, useRef, useState} from 'react';
import {Manager} from 'react-popper';
import {Popper} from 'react-popper';
import {Reference} from 'react-popper';
import copy from 'copy-to-clipboard';
import {t} from './i18n';
export function WalletAddress(props) {
const [showPopup, setShowPopup] = useState(false);
const {symbol, id, name} = props;
const walletIdRef = useRef(null);
const buttonClicked = (e) => {
setShowPopup(true);
const walletId = walletIdRef.current;
const value = walletId.getAttribute('value');
copy(value);
};
const renderPopper = () => {
const classes = ['notify-popup'];
if (showPopup) {
classes.push('start');
}
return (
<Popper placement="top">
{({ref, style, placement, arrowProps}) => (
<div className={classes.join(' ')} ref={ref} style={style} data-placement={placement}>
{ t('t-copied') }
<div className="arrow" ref={arrowProps.ref} style={arrowProps.style} />
</div>
)}
</Popper>
);
};
useEffect(() => {
if (showPopup) {
setTimeout(() => { setShowPopup(false); }, 100);
}
}, [showPopup]);
const popup = renderPopper();
return (
<li>
<div className="currency-name">{ name } ({ symbol })</div>
<input ref={walletIdRef} className="wallet-id" type="text" value={id} readOnly />
<Manager>
<Reference>
{({ref}) => (
<button type="button" className="copy-button" ref={ref} onClick={buttonClicked}></button>
)}
</Reference>
{popup}
</Manager>
</li>
);
}
import React from 'react';
import {WalletAddress} from './wallet_address';
export function WalletAddresses(props) {
const {wallets} = props;
const walletAddresses = wallets.map((wallet) => {
return (<WalletAddress key={wallet.symbol} {...wallet} />);
});
return (
<ul>
{walletAddresses}
</ul>
);
}
{% block content %}
<div class="cryptocurrency">
<div class="payment-other-div container">
<a class="hyperlinks links" href="/donate">{{ _('Want to donate by credit card or PayPal?') }}</a>
</div>
<div class="intro-text-section container">
<div class="intro-text">
<div class="preamble">
<p>
{{ _('Donate using BTCPayServer') }}
</p>
</div>
<div class="btc-form">
<form method="POST" action="https://fund.btcpayserver.org/api/v1/invoices" style="width:418px; margin:auto;">
<input type="hidden" name="storeId" value="9Ac1k57DGMpL2QeYeqSiNcpq6tor6NAGgiuYYij3tPaE" />
<div style="text-align:center;display:block;">
<div>
<button style="cursor:pointer; font-size:25px; line-height: 25px; background: rgba(0,0,0,.1); height: 30px; width: 45px; border:none; border-radius: 60px; margin: auto;" onclick="event.preventDefault(); var price = parseInt(document.querySelector('#btcpay-input-price').value); if ('-' == '-' && (price - 1) < 1) { return; } document.querySelector('#btcpay-input-price').value = parseInt(document.querySelector('#btcpay-input-price').value) - 1;">
-
</button>
<input type="text" id="btcpay-input-price" name="price" min="1" max="20" step="1" value="10" style="border: none; background-image: none; background-color: transparent; -webkit-box-shadow: none ; -moz-box-shadow: none ; -webkit-appearance: none ; width: 3em; text-align: center; font-size: 25px; margin: auto; border-radius: 5px; line-height: 35px; background: #fff;" oninput="event.preventDefault();isNaN(event.target.value) || event.target.value <= 0 ? document.querySelector('#btcpay-input-price').value = 10 : event.target.value" />
<button style="cursor:pointer; font-size:25px; line-height: 25px; background: rgba(0,0,0,.1); height: 30px; width: 45px; border:none; border-radius: 60px; margin: auto;" onclick="event.preventDefault(); var price = parseInt(document.querySelector('#btcpay-input-price').value); if ('+' == '-' && (price - 1) < 1) { return; } document.querySelector('#btcpay-input-price').value = parseInt(document.querySelector('#btcpay-input-price').value) + 1;">
+
</button>
</div>
<select onmouseover="this.style.border='solid #ccc 1px'; this.style.padding='0px'" onmouseout="this.style.border='0'; this.style.padding='1px'" onchange="document.querySelector('input[type = hidden][name = currency]').value = event.target.value" style="border: 0; display: block; padding: 1px; margin: auto auto 5px auto; font-size: 11px; background: 0 0; cursor: pointer;">
<option value="USD">USD</option>
<option value="GBP">GBP</option>
<option value="EUR">EUR</option>
<option value="BTC">BTC</option>
</select>
</div>
<input type="hidden" name="currency" value="USD" />
<input type="image" src="https://fund.btcpayserver.org/img/paybutton/pay.png" name="submit" style="width:209px; display:block; margin:auto;" alt="Pay with BtcPay, Self-Hosted Bitcoin Payment Processor">
</form>
<a class="btc-onion-link" href="http://sqgf7aihkpxwdtcb3zjf62jo63o5yqjckukioas3aropdmcay4ymepid.onion/apps/2xcGbmQoXHddtFPs5oYJJ79DCrFC/pos">{{ _('Donate using the BTC onion site') }}</a>
</div>
<div class="preamble">
<p>
{{ _('Donate using wallet addresses') }}
</p>
</div>
<p>
{{ _('Please fill out this form and then send your coins to the appropriate wallet.') }} {{ _('Filling out the form is not necessary, but doing so will notify us about your donation quickly, allow us to send you an acknowledgement, and let us know your communication preferences.') }}
</p>
<p>
{{ _('Below you will find the cryptocurrencies we accept and our wallet addresses.') }} {{ _('The wallet addresses will be displayed again after you complete the form.') }} {{ _('Please make sure to copy the wallet addresses exactly when making your donation, as we cannot recover funds sent to the wrong wallet.') }}
</p>
<p>
{{ _('If you have any questions, or would like to donate a cryptocurrency not listed below, please email us at giving@torproject.org.') }}
</p>
</div>
</div>
<noscript>
<form action="/cryptocurrency/donate" method="POST">
<div class="section">
<div class="form-column">
<h4>{{ _('Your Info') }}</h4>
<div class="form-fields">
<input class="field" name="firstName" placeholder="{{ _('First Name') }}" maxlength="256" type="text">
<input class="field" name="lastName" placeholder="{{ _('Last Name') }}" maxlength="256" type="text">
<div class="mailing-list-opt-in checkbox-row">
<input name="mailingListOptIn" id="mailingListOptIn" type="checkbox">
<label class="light" for="mailingListOptIn">{{ _('Start sending me email updates about the Tor Project!') }}</label>
</div>
<label for="estimatedDonationDate">{{ _('Estimated Donation Date:') }}</label>
<input name="estimatedDonationDate" id="estimatedDonationDate" type="date" required="">
<input class="field" name="email" placeholder="{{ _('Email') }}" maxlength="256" type="text" required="">
<select class="field required" name="cryptocurrencyType" required="">
<option value="">{{ _('Choose a Currency') }}</option>
{% for wallet in wallets %}
<option value="{{ wallet.symbol }}">{{ wallet.name }}</option>
{% endfor %}
<input class="field" name="currencyAmount" placeholder="{{ _('Currency Amount') }}" maxlength="256" type="text" required="">
</div>
<br/>
<div class="section button-section">
<input class="donate button" type="submit" value="{{ _('Report Donation') }}">
</div>
</div>
<div class="wallet-column">
<h4>{{ _('Wallet Addresses') }}</h4>
<ul>
{% for wallet in wallets %}
<li>
<div class="currency-name">{{ wallet.name }} ({{ wallet.symbol }})</div>
<input class="wallet-id" type="text" readonly="" value="{{ wallet.id }}">
</li>
{% endfor %}
</ul>
</div>
</div>
</form>
</noscript>
<div id="cryptocurrency-form" class="container"></div>
<div class="js-translatable-strings" style="display: none;">
<div id="t-copied">{{ _('Copied') }}</div>
<div id="t-currency-amount-must-be-number">{{ _('Currency Amount must be a number.') }}</div>
<div id="t-choose-currency">{{ _('Choose a Currency') }}</div>
<div id="t-currency-amount">{{ _('Currency Amount') }}</div> <div id="t-estimated-donation-date">{{ _('Estimated Donation Date') }}</div>
<div id="t-donate-anonymously">{{ _("I'd like to make my donation anonymous.") }}</div>
<div id="t-email">{{ _('Email') }}</div>
<div id="t-first-name">{{ _('First Name') }}</div>
<div id="t-last-name">{{ _('Last Name') }}</div>
<div id="t-report-donation">{{ _('Report Donation') }}</div>
<div id="t-start-email-updates">{{ _('Start sending me email updates about the Tor Project!') }}</div>
<div id="t-wallet-addresses">{{ _('Wallet Addresses') }}</div>
<div id="t-your-info">{{ _('Your Info') }}</div>
</div>
</div>
<script type="text/javascript">
const cryptoReactComponent = {
id: 'cryptocurrency-form',
name: 'CryptocurrencyForm',
props: {
'wallets': [
{
'symbol': 'REP',
'id': '0x19DdD94B94D3c68385c897846AB44Ac99DBFAe0f',
'name': 'Augur'
},
{
'symbol': 'XBT',
'id': '1JADsmDFX9d2TXis63S9F9L8eDAXwJmnWE',
'name': 'Bitcoin',
},
{
'symbol': 'BCH',
'id': '1BK6d6vfLPDqZaBeKRd15oK5yxuLymi1Ry',
'name': 'Bitcoin Cash',
},
{
'symbol': 'DASH',
'id': 'Xkknor7eBf6vADMtP8VuNTPKsTsatCp8Xe',
'name': 'Dash',
},
{
'symbol': 'ETH',
'id': '0x19DdD94B94D3c68385c897846AB44Ac99DBFAe0f',
'name': 'Ether',
},
{
'symbol': 'LTC',
'id': 'LNAifc8nfjtDJ8azRPiancbZSBftPzhfzb',
'name': 'Litecoin',
},
{
'symbol': 'XMR',
'id': '',
'name': 'Monero',
},
{
'symbol': 'XLM',
'id': 'GABWGQEQESRX5TKDTPIYJFPKGJDMEW6VLOOLBTIFPJIN7XT6KAFXJQPJ',
'name': 'Stellar Lumen',
},
{
'symbol': 'ZEC',
'id': 'zs1kpat3qseujnnukms9yjkx7w3kgzev7jxhauc6cy2s3mupmvsvkvw04u3s35sffmv57leznctn5h',
'name': 'Zcash'
},
{
'symbol': 'XDG',
'id': 'DGvn1HLeMaCZEZZYUeBWBhUCJiS2hjzbGd',
'name': 'Dogecoin',
}
],
'donateProccessorBaseUrl': `{{ bag('donate', envvars('ENV'), 'donateProccessorBaseUrl') }}`,
}
};
if (window.reactComponents) {
window.reactComponents.push(cryptoReactComponent);
} else {
window.reactComponents = [cryptoReactComponent];
}
</script>
<script type="text/javascript" src="/static/gen/donate.js"></script>
{% endblock %}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment