Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cfg/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ module.exports = {
port: dfltPort,
getDefaultModules: getDefaultModules
};

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"release:patch": "npm version patch && npm publish && git push --follow-tags",
"serve": "node server.js --env=dev",
"serve:dist": "node server.js --env=dist",
"start": "node server.js --env=dev",
"start": "nodemon server.js --env=dev",
"test": "karma start",
"test:watch": "karma start --autoWatch=true --singleRun=false"
},
Expand All @@ -38,7 +38,7 @@
"eslint-plugin-react": "^6.0.0",
"file-loader": "^0.9.0",
"glob": "^7.0.0",
"isparta-instrumenter-loader": "^1.0.0",
"isparta-loader": "^1.0.0",
"karma": "^1.0.0",
"karma-chai": "^0.1.0",
"karma-coverage": "^1.0.0",
Expand All @@ -49,6 +49,7 @@
"karma-webpack": "^1.7.0",
"minimist": "^1.2.0",
"mocha": "^3.0.0",
"nodemon": "^1.11.0",
"null-loader": "^0.1.1",
"open": "0.0.5",
"phantomjs-prebuilt": "^2.0.0",
Expand Down
48 changes: 31 additions & 17 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,33 @@ Routing functionality bneeds extra npm's specifically
npm install -S react-router
npm install -S history

----------------------------
@spal23 - Added some very basic routing.

---------------------------- June 2017
@spal23 - Configured the topic based home page

Added two components, both used on the home page. The first is Topics.jsx, the second is MembersList.jsx. They can be found in \src\components\Common

Topics displays a group of href shortcuts loaded in three columns. The fun here was rendering all of the topics with a forced width css, hidden. Then, using refs get the heights of each topic element (while they are hidden - but after they were mounted). Using this height array the topics were re-rendered and placed based on a shortest column algorithm. Topics can be clicked through to generate a new tab in the browser.

Memberslist uses CORS (which has to be enabled in the browser) to link to the Meetup API and request the group members of NottsJS. The members picture, bio and name are then loaded into a div to the right of the home page.

Topics displayed on home page are loaded from the object array defined in \src\data\topiclist.js.

From here ...
1. Could do with a database to hold topic info for fast retrieval, rather than using href links to populate the page.
Would also look at doing a cut and paste to copy other user specific shortcuts to the page automatically. Each home page would be user specific then.
2. Page format could be more automated by passing props in from the template to allow page structure to change programatically. Currently page width is hard coded.
3. CSS could be more optimised. Currently CSS is bound to the components as per Reacts guidelines however I am sure this could be optimised by a more experienced CSS programmer than myself.
4. The header picture could be higher res and thinner. It would be neat to have a slide show feature there as well.
5. Footer needs to be organised along the lines of the original web site.
6. CORS link in the Memberslist.jsx component needs extending to bring in pictures of all of the groups members. Currently this is limited to the first 200 records. Unsure as to why.

Next ...
1. I will look at doing a page to automatically feed into meetup so that we can setup meetings from our own page outide of the meetup site. Basicaly getting into the meetup API a little bit more.


---------------------------- April 2017
@spal23 - Added some very basic routing

For info to those unsure about things (aka me)
1. npm start calls to server.js
Expand All @@ -31,20 +56,9 @@ Note - If running with sublime and you want to add a .jsx extension beutifier
2. Open a .jsx file
3. Select View from the menu
4. Then Syntax -> Open all with current extension as.. -> Babel - Javascript (Babel)

The routing method was based on the article from ..
https://scotch.io/tutorials/routing-react-apps-the-complete-guide
References are:
http://gunnariauvinen.com/getting-es6-syntax-highlighting-in-sublime-text/
https://scotch.io/tutorials/routing-react-apps-the-complete-guide

I have gone with browser history for now rather than hash history if someone knows what they are doing feel free to change that about.

I have played around with props, passing back functions and booleans to the header page
to provide switched layouts just to see if it can be done. All of the trial and error work has been done on the /training route and mapped out to / and /about when I have go the hand of it all.

Changes made to ....

Components folder
index.jsx
package.json
readme.md

------------------------------
------------------------------
26 changes: 24 additions & 2 deletions src/components/Common/Footer.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@

import React from 'react';
import { Link } from 'react-router';

export default class Footer extends React.Component {
render() {
var navbar2 = {
paddingRight: '10px',
paddingLeft: '10px',
color: 'black'
}
var footerStyle = {
position: 'relative',
width: '800px',
marginLeft: 'auto',
marginRight: 'auto',
bottom: '0px',
height: '200px',
backgroundColor: 'pink'
}
return (
<footer>FOOTER LOCATION</footer>
);
<div style={footerStyle} >
<ul>
<br/>
<Link style={navbar2} to='/'>Home</Link>
<Link style={navbar2} to='/about'>About</Link>
<Link style={navbar2} to='/training'>Training</Link>
</ul>
</div>
);
}
}
64 changes: 57 additions & 7 deletions src/components/Common/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,69 @@ import React from 'react';
import { Link } from 'react-router';

export default class Header extends React.Component {

/*
static propTypes = {
title: React.PropTypes.string.isRequired
}
*/

render() {
const { title } = this.props;
var headerStyle = {
position: 'relative',
width: '800px',
top: '0px',
marginLeft: 'auto',
marginRight: 'auto'
}
var navbar = {
position: 'absolute',
height: '20px',
bottom: '10px'
}
var navbar2 = {
paddingRight: '10px',
paddingLeft: '10px',
color: 'grey'
}
var logofloat = {
position: 'absolute',
top: '20px',
left: '20px',
backgroundColor: 'white'
}
var sponsorfloat = {
position: 'absolute',
top: '20px',
right: '20px',
backgroundColor: 'white'
}
var sponsorstack = {
position: 'absolute',
top: '70px',
right: '20px',
backgroundColor: 'white'
}
var sponsorstack2 = {
position: 'absolute',
top: '180px',
right: '20px',
backgroundColor: 'white'
}
return (
<header>
<h1>Notts JS - {title}</h1>
<Link to='/'>Home</Link>
<Link to='/about'>About</Link>
<Link to='/training'>Training</Link>
</header>
<div style={headerStyle} >
<img src='../../images/Header_01.jpg' width="800px" />
<img style={logofloat} src='../../images/nottsjs.png' width="70px" />
<img style={sponsorfloat} src='../../images/mozlogo.jpeg' width="90px" />
<img style={sponsorstack} src='../../images/jhlogo.jpeg' width="90px" />
<img style={sponsorstack2} src='../../images/rebellogo.jpeg' width="90px" />
<div style={navbar} >
<Link style={navbar2} to='/'>Home</Link>
<Link style={navbar2} to='/about'>About</Link>
<Link style={navbar2} to='/training'>Training</Link>
</div>
</div>
);
}
}

165 changes: 165 additions & 0 deletions src/components/Common/MembersList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/* eslint no-console: 0*/

import React from 'react';

// Support Functions
function createCORSRequest(method, url) {
/*
Courtesy of ...
https://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
*/
var xhr = new XMLHttpRequest();
if ('withCredentials' in xhr) {

// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHT*-TPRequest2 objects.
xhr.open(method, url, true);
console.log('--- found withCredentials property')

} else if (typeof XDomainRequest != 'undefined') {
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);

} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;

}
return xhr;
}

// MEMBER COMPONENT =====================================
class Member extends React.Component {
constructor(props){
super(props); // Calls the constructor of the parent class. In this case Memberslist
}

// MEMBER return method
render(){
var pstyle = {
fontSize: '12px'
}
var spanstyle = {
color: 'green',
fontSize: '11px'
}
var imgStyle = {
borderRadius: '15px 15px 15px 15px'
}
var td = this.props.dataString
if ('photo' in td) {
return (
<div>
<img style={imgStyle} src={td.photo.thumb_link} width="80px" />
<p style={pstyle}>"{td.bio}" - <span style={spanstyle} >{td.name}</span></p>
</div>
);
} else {
return (
<div>
<p style={pstyle}>"{td.bio}" - <span style={spanstyle} >{td.name}</span></p>
</div>
);
}
}
}

// MEMBERSLIST COMPONENT =================================
export default class MembersList extends React.Component {
constructor(props){
super(props); // Calls the constructor of the parent class. In this case React.component
this.membersdata = getTestData();
this.state = { showReceivedList: false };
console.log('--- MembersList Constructor Loading ...');

// Kickoff the fetch of the members list'
var url = 'https://www.google.com'
var xhr = createCORSRequest('GET', url);
if (!xhr) {
console.log('--- Sadly CORS is not Supported')
throw new Error('CORS not supported');
} else {
console.log('--- great news CORS is supported')
}

/*
CORS NOTE. When running this code in Localhost on Chrome
you need to have the CORS Toggle extension installed and running. Otherwise
chrome kicks out errors to do with authentication.
*/

// HTTP request to meetup for latest members list.
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.meetup.com/NottsJS/members?&key=7121206f695127cd116f2743281550', true);

// HTTP CORS event handlers
// xhr.onreadystatechange is replaced by xhr.onload as of HTML 5 (2014).
xhr.onload = this.processRequest;
xhr.onerror = () => {
console.log('--- CORS Event failed - There was an error!');
};

// Kickoff HTTP async request
xhr.withCredentials = false;
xhr.send();
console.log('--- Memberslist called for Asynchronously');
}

// MEMBERSLIST EVENT HANDLER (CORS)
// 'this' could have been configured using bind by placing the following in the constructor above.
// this.processRequest = this.processRequest.bind(this);
// Doing this would have meant that the arrow function need not have been used below.
processRequest = e => {
console.log(e);
var xhr = e.target;
if (xhr.readyState == 4 && xhr.status == 200) {
this.membersdata = JSON.parse(xhr.responseText);
console.log('--- Changing state to cause re-render with new list');
this.setState({ showReceivedList: true }); // A function taking an object as the argument
}
console.log('--- ' + e.target.status + ' ' + this.state.showReceivedList);
}

// MEMBERSLIST return method with styling
render(){
var assideStyle = {
position: 'absolute',
float: 'right',
display: 'inline-block',
width: '100px',
height: '784px',
margin: '2px',
border: '1px solid black',
padding: '5px',
backgroundColor: 'pink',
overflow: 'scroll'
}
console.log('--- Rendering the members list');
return(
<div style={assideStyle}>
{this.membersdata.map((item, ix) => {
return (
<Member key={ix} dataString={item} />
)}
)}
</div>
);
}
}

function getTestData() {
return( [{
id: 2890627,
name: 'Nomad3k',
bio: 'Main organiser and React architect for the NottsJS group',
photo: {
id: 252816582,
thumb_link: 'https://secure.meetupstatic.com/photos/member/8/e/e/6/thumb_252816582.jpeg'
},
link: 'https://www.meetup.com/NottsJS/members/2890627/'
}]);
}


Loading