Skip to content

Commit

Permalink
Migrates pages module (#1412)
Browse files Browse the repository at this point in the history
* create two components. still have an error from board

* resolve error with string parameter for  Board.js

* remove old foundation and manifesto-text in angular

* home component migration to react

* Implements boards and manifesto in home component

* Implements tribe circles with styles

* Implements tribes API

* Finishes react migration of home page

* Implements FAQ translations

* Refractors board credits

* Migrates FAQ pages

* WIP on pages migration

* Migrates team page

* Migrates donate, rules, privacy, navigation and guide component

* fixes errors for merging

* removes onDisplayPhoto and onHidePhoto

Co-authored-by: Nick Sellen <[email protected]>

* Handle useEffect with array value as dependency

As it only checks object identity, when we pass in a new
array each time (even with the same values) it considers that
changed, but we only want it changes if the values _in_ the
array change. Achieved with `.join(' ')`ing the values.

* Fix subscribe/unsubscribe of events

Previously was subscribing in the useEffect unsubscribe hook.

I split it into two useEffect hooks as each call to `$on` returns
it's own unsubscribe function that we can pass directly to the
`useEffect` hook.

* Fix calculation of photo credits count

Using ++/-- it sometimes got it wrong (as it also got set to 0 on
page change), and was at 0 even when there was a photo credit.

This meant the photo credits were hidden when they shouldn't be.

* Mock angular-compat to fix failing tests

* Prettier-fix

* Remove unused file

* Remove uneeded/done TODOs/comments

* Add credits $broadcast test

Co-authored-by: Dario Hornsteiner <[email protected]>
Co-authored-by: Nick Sellen <[email protected]>
Co-authored-by: Nick Sellen <[email protected]>
  • Loading branch information
4 people authored May 22, 2020
1 parent a7b7f22 commit 6aaa013
Show file tree
Hide file tree
Showing 47 changed files with 3,662 additions and 2,885 deletions.
29 changes: 20 additions & 9 deletions modules/core/client/components/Board.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import isArray from 'lodash/isArray';

import { selectPhoto } from '../services/photos.service';
import { $broadcast } from '@/modules/core/client/services/angular-compat';

/**
* @param {string[]|string} names - array of names or a single name
Expand All @@ -24,9 +27,8 @@ function selectName(names) {
*/
export default function Board({
names = 'bokeh',
style = null,
children,
onDisplayPhoto = () => {},
onHidePhoto = () => {},
className,
...rest
}) {
Expand All @@ -44,15 +46,25 @@ export default function Board({

// inform the parent that the photo is displayed
// ...useful e.g. for displaying photo credits elsewere
onDisplayPhoto(photoObject);
$broadcast('photoCreditsUpdated', photoObject);

// inform the parent that the photo is not displayed anymore
return () => onHidePhoto(photoObject);
}, []);
return () => {
$broadcast('photoCreditsRemoved', photoObject);
};
}, [isArray(names) ? names.join(' ') : names]);

const style = photo ? { backgroundImage: `url("${photo.imageUrl}")` } : null;
if (photo) {
style
? (style.backgroundImage = `url("${photo.imageUrl}")`)
: (style = { backgroundImage: `url("${photo.imageUrl}")` });
}
return (
<section style={style} className={classNames('board', className)} {...rest}>
<section
style={{ ...style }}
className={classNames('board', className)}
{...rest}
>
{children}
</section>
);
Expand All @@ -63,8 +75,7 @@ Board.propTypes = {
PropTypes.string,
PropTypes.arrayOf(PropTypes.string),
]).isRequired,
style: PropTypes.object,
className: PropTypes.string,
children: PropTypes.node,
onDisplayPhoto: PropTypes.func,
onHidePhoto: PropTypes.func,
};
76 changes: 76 additions & 0 deletions modules/core/client/components/BoardCredits.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// import React from 'react';
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { $on } from '@/modules/core/client/services/angular-compat';
import omit from 'lodash/omit';

/**
* Board Credits component Print out credits for photos used at the page.
* Usage: `<BoardsCredits {...props}><WrappedComponent /></Tooltip>`
*
* @param {object} photos - object containing photo objects accessible by their keys
*/
export default function BoardCredits({ photoCredits: initialPhotoCredits }) {
const { t } = useTranslation('messages');

const [photoCredits, setPhotoCredits] = useState(initialPhotoCredits);

useEffect(
() =>
$on('photoCreditsUpdated', (scope, photo) =>
setPhotoCredits({ ...photoCredits, ...photo }),
),
[],
);

useEffect(
() =>
$on('photoCreditsRemoved', (scope, photo) =>
setPhotoCredits(omit(photoCredits, Object.keys(photo))),
),
[],
);

const credits = Object.keys(photoCredits).map(key => {
return { key, ...photoCredits[key] };
});

if (credits.length === 0) return null;

return (
<small className="font-brand-light">
<span className="boards-credits">
{credits.length === 1 && <span>Photo by </span>}
{credits.length > 1 && <span>Photos by </span>}
{credits.map((credit, index) => (
<span key={credit.key}>
<a href={credit.url} rel="noopener">
{credit.name}
</a>
{credit.license && (
<span>
{' '}
(
<a
href={credit.license_url}
title={t('License')}
rel="license noopener"
aria-label={t('License')}
>
{credit.license}
</a>
)
</span>
)}
{index < credits.length - 1 && <span>, </span>}
</span>
))}
</span>
</small>
);
}

BoardCredits.propTypes = {
photoCredits: PropTypes.object,
};
4 changes: 2 additions & 2 deletions modules/core/client/controllers/app.client.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,14 @@ function AppController(
*/
$scope.$on('photoCreditsUpdated', function (scope, photo) {
angular.extend(vm.photoCredits, photo);
vm.photoCreditsCount++;
vm.photoCreditsCount = Object.keys(vm.photoCredits).length;
});

$scope.$on('photoCreditsRemoved', function (scope, photo) {
const photoName = Object.keys(photo)[0];
// @TODO inconsistent results when there is the same photo displayed multiple times
delete vm.photoCredits[photoName];
vm.photoCreditsCount--;
vm.photoCreditsCount = Object.keys(vm.photoCredits).length;
});
}

Expand Down
151 changes: 151 additions & 0 deletions modules/pages/client/components/Donate.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import React from 'react';
import Board from '@/modules/core/client/components/Board.js';
import { Trans, useTranslation } from 'react-i18next';

export default function Donate() {
const { t } = useTranslation('pages');

return (
<>
<Board names="forestpath">
<div className="container">
<div className="row">
<div className="col-xs-12 text-center">
<br />
<br />
<i className="icon-3x icon-heart-alt"></i>
<br />
<br />
<h2>{t('Support Trustroots')}</h2>
</div>
</div>
</div>
</Board>

<section className="container container-spacer">
<div className="row">
<div className="col-xs-12 col-sm-6 col-md-offset-1 col-md-5">
<p className="lead">
<Trans t={t} ns="pages">
Trustroots is run entirely by donations. We are a non-profit{' '}
<a href="/foundation">foundation</a> registered in the United
Kingdom in March 2015.
</Trans>
</p>

<h4>{t('How will my donation be used?')}</h4>
<p>
{t(
"Most our expenses are tech related; servers, services, domains and bandwidth. Additionally we have expenses from governing the foundation, such as legal consultation, handling our finances and accounting. In the future we consider paying salaries to get some of the work done. This said, we're mainly a volunteer organisation and that won't change. We are working on opening up our expenditures and governance soon.",
)}
</p>
<br />

<h4>{t('Is my donation tax deductible?')}</h4>
<p>{t('Unfortunately not at the moment.')}</p>
<br />

<h4>{t('Which currencies do you accept?')}</h4>
<p>
{t(
'You can donate via PayPal, which currently accepts nearly two dozen currencies.',
)}
</p>
<br />

<h4>{t('Can I donate bitcoin?')}</h4>
<p>{t('Yes!')}</p>
<br />

<h4>
{t(
'I’m unable to give money at this time, are there other ways I can help?',
)}
</h4>
<p>
<Trans t={t} ns="pages">
Yes! <a href="/volunteering">Become a volunteer</a> and make a
difference.
</Trans>
</p>

<hr />

<p>
<a href="/donate/help">{t('Problems donating?')}</a>
</p>

<br />
</div>
<div className="col-xs-12 col-sm-6 col-md-5">
<p className="lead">
<em>
{t(
"We're currently working on setting up ways to receive donations. Until that, this page gives you preliminary information about our funding model.",
)}
</em>
</p>
<hr />
<h2>{t('Ways to Give')}</h2>
<h3>{t('Credit/debit card')}</h3>
{t(
"We don't have a credit card transfer set up yet at this point.",
)}
<h3>{t('Bank transfer')}</h3>
{t("We don't have a bank account set up yet at this point.")}
<h3>Bitcoin</h3>
<Trans t={t} ns="pages">
<a href="/support">Contact us</a> if you want to donate through
Bitcoin.
</Trans>
<h3>PayPal</h3>
<Trans t={t} ns="pages">
<a href="/support">Contact us</a> if you want to donate through
PayPal.
</Trans>
<h3>{t('Referal programs')}</h3>
<h4>{t('Namecheap')}</h4>
<Trans t={t} ns="pages">
We use and recommend Namecheap for domains, partly because
they&apos;re a{' '}
<a href="https://www.namecheap.com/about/causes.aspx">
responsible company
</a>{' '}
and foremost they do a great job. Sign up via{' '}
<a href="https://www.namecheap.com/?aff=90636">this link</a> and
we&apos;ll get little bit in return.
</Trans>
<br />
<h4>DigitalOcean</h4>
<Trans t={t} ns="pages">
Our servers are hosted at reliable and easy to use DigitalOcean.
Sign up via{' '}
<a href="https://www.digitalocean.com/?refcode=6dc078966c9c">
this link
</a>{' '}
and when you start using their VPS service, we get 25$ to cover
our hosting, you get 10$.
</Trans>
<hr />
<p>
<small>
<Trans t={t} ns="pages">
By donating, you agree to share your personal information with
the Trustroots Foundation, the non-profit organisation running
Trustroots.org, pursuant to our{' '}
<a href="/donate/policy">donor policy</a>. Trustroots
Foundation is located in the United Kingdom. We do not sell or
trade your information to anyone.
</Trans>
</small>
</p>
</div>
</div>
{/* /.row */}
</section>
{/* /.container */}
</>
);
}

Donate.propTypes = {};
Loading

0 comments on commit 6aaa013

Please sign in to comment.