Skip to content

Commit

Permalink
Migrate a header for Tribes List to React (#1137)
Browse files Browse the repository at this point in the history
Also partially migrate the tr-boards directive to React
  • Loading branch information
mrkvon committed Jan 19, 2020
1 parent 9e79648 commit 8d8f3eb
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 21 deletions.
62 changes: 62 additions & 0 deletions modules/core/client/components/Board.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { selectPhoto } from '../services/photos.service';

/**
* @param {string[]|string} names - array of names or a single name
*
* @returns {string} the provided name or randomly picked name from array
*/
function selectName(names) {
return Array.isArray(names) ? names[Math.floor(Math.random() * names.length)] : names;
}

/**
* Partially migrated tr-boards directive
* modules/core/client/directives/tr-boards.client.directive.js
*
* @TODO implement tr-boards-ignore-small directive
* @TODO implement primary, inset, error and maybe other attributes, which are currently board classes
* and which could become attributes <Board primary inset error names="bokeh" />
*/
export default function Board({ names='bokeh', children, onDisplayPhoto=() => {}, onHidePhoto=() => {}, className, ...rest }) {

const [photo, setPhoto] = useState(null);

useEffect(() => {
// pick a name from provided names
const selectedName = selectName(names);
// select an appropriate photo by name
const photo = selectPhoto(selectedName);
const photoObject = { [selectedName]: photo };

// update the state with the selected photo
setPhoto(photo);

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

// inform the parent that the photo is not displayed anymore
return () => onHidePhoto(photoObject);
}, []);

const style = photo ? { backgroundImage: `url("${photo.imageUrl}")` } : null;
return (
<section style={style} className={classNames('board', className)} {...rest}>
{children}
</section>
);
}

Board.propTypes = {
names: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string),
]).isRequired,
className: PropTypes.string,
children: PropTypes.node,
onDisplayPhoto: PropTypes.func,
onHidePhoto: PropTypes.func,
};
7 changes: 7 additions & 0 deletions modules/core/client/controllers/app.client.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ function AppController(
vm.photoCreditsCount++;
});

$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--;
});

}

/**
Expand Down
43 changes: 43 additions & 0 deletions modules/tribes/client/components/TribesHeader.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import Board from '@/modules/core/client/components/Board';

export default function TribesHeader({ isLoggedIn, onDisplayPhoto, onHidePhoto }) {

const { t } = useTranslation('tribes');

return (
<Board
names="tribes-1"
className="tribes-header"
onDisplayPhoto={onDisplayPhoto}
onHidePhoto={onHidePhoto}
>
<div className="container">
<div className="row">
<div className="col-xs-12 text-center">
<br /><br />
<h2>{t('Discover Tribes')}</h2>
<br />
<p className="lead">
{t('Joining Tribes helps you find likeminded Trustroots members.')}
</p>
{!isLoggedIn && <div>
<hr className="hr-white hr-xs"/>
<a href="/signup" className="btn btn-action btn-default">
{t('Sign up with Trustroots')}
</a>
</div>}
</div>
</div>
</div>
</Board>
);
}

TribesHeader.propTypes = {
isLoggedIn: PropTypes.bool.isRequired,
onDisplayPhoto: PropTypes.func.isRequired,
onHidePhoto: PropTypes.func.isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ angular
.controller('TribesListController', TribesListController);

/* @ngInject */
function TribesListController(tribes, $state, Authentication, TribeService) {
function TribesListController(tribes, $state, Authentication, TribeService, $scope) {

// ViewModel
const vm = this;
Expand All @@ -22,4 +22,15 @@ function TribesListController(tribes, $state, Authentication, TribeService) {
TribeService.fillCache(angular.copy(tribe));
$state.go('tribes.tribe', { 'tribe': tribe.slug });
}

/**
* Emit photo credits info
* @TODO remove this
*/
vm.addPhotoCredits = function addPhotoCredits(photo) {
$scope.$emit('photoCreditsUpdated', photo);
};
vm.removePhotoCredits = function removePhotoCredits(photo) {
$scope.$emit('photoCreditsRemoved', photo);
};
}
25 changes: 5 additions & 20 deletions modules/tribes/client/views/tribes-list.client.view.html
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
<section class="board tribes-header" tr-boards="'tribes-1'">
<div class="container">
<div class="row">
<div class="col-xs-12 text-center">
<br><br>
<h2>Discover Tribes</h2>
<br>
<p class="lead">
Joining Tribes helps you find likeminded Trustroots members.
</p>
<div ng-if="!app.user">
<hr class="hr-white hr-xs"/>
<a ui-sref="signup" class="btn btn-action btn-default">
Sign up with Trustroots
</a>
</div>
</div>
</div>
</div>
</section>
<tribes-header
isLoggedIn="!!app.user"
onDisplayPhoto="tribesList.addPhotoCredits"
onHidePhoto="tribesList.removePhotoCredits"
></tribes-header>

<section class="container container-spacer">

Expand Down

0 comments on commit 8d8f3eb

Please sign in to comment.