Commit 17561a20 authored by Sam Gluck's avatar Sam Gluck
Browse files

- Routing

- Login page
parent cee34b61
......@@ -83,7 +83,7 @@ module.exports = {
// https://github.com/facebookincubator/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx', '.tsx', '.ts'],
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx', '.tsx', '.ts', '.graphql'],
alias: {
'~': paths.appSrc
},
......@@ -124,6 +124,10 @@ module.exports = {
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
{
test: /\.graphql$/,
loader: require.resolve('graphql-tag/loader'),
},
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
......
......@@ -78,7 +78,7 @@ module.exports = {
// https://github.com/facebookincubator/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx', '.tsx', '.ts'],
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx', '.tsx', '.ts', '.graphql'],
alias: {
'~': paths.appSrc,
},
......@@ -120,6 +120,10 @@ module.exports = {
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
{
test: /\.graphql$/,
loader: require.resolve('graphql-tag/loader'),
},
// "url" loader works just like "file" loader but it also embeds
// assets smaller than specified size as data URLs to avoid requests.
{
......
......@@ -4,21 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#FF7500">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet">
<title>MoodleNet</title>
</head>
......@@ -27,15 +14,5 @@
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
import ApolloClient from 'apollo-boost';
import resolvers from './resolvers';
export default new ApolloClient({
clientState: {
defaults: {
user: {
__typename: 'User',
isAuthenticated: false,
data: null
}
},
resolvers
}
});
import updateUser from './updateUser';
export default {
Mutation: {
updateUser
}
};
const { GetUserQuery } = require('../../graphql/GET_USER.client.graphql');
export default (_, { isAuthenticated, data }, { cache }) => {
const previousState = cache.readQuery({
query: GetUserQuery
});
const cacheData = {
user: {
...previousState.user,
isAuthenticated,
data
}
};
cache.writeQuery({
query: GetUserQuery,
data: cacheData
});
return null;
};
import * as React from 'react';
import styled from '../../../themes/styled';
import { Link } from 'react-router-dom';
const moodleNetLogo = require('../../../static/img/moodlenet-logo.png');
const LogoH1 = styled.h1`
margin: 0;
`;
export default () => (
<LogoH1>
<Link to="/" title="MoodleNet">
<img src={moodleNetLogo} alt="MoodleNet" />
</Link>
</LogoH1>
);
import { Body as ZenBody } from '@zendeskgarden/react-chrome';
import styled from '../../../themes/styled';
export default styled(ZenBody)`
flex-grow: 1;
`;
......@@ -2,55 +2,113 @@ import * as React from 'react';
import { Menu as ZenMenu, Item } from '@zendeskgarden/react-menus';
import { Avatar } from '@zendeskgarden/react-avatars';
import styled from '../../../themes/styled';
const avatar = require('../../../static/img/avatar.png');
const search = require('../../../static/img/search.png');
const notifications = require('../../../static/img/notifications.png');
export default function Menu() {
return (
<div className="Menu">
<div className="Menu__item">
<ZenMenu
trigger={({ ref }) => (
<img ref={ref} width={30} height={30} src={search} alt="Search" />
)}
>
<Item>1</Item>
<Item>2</Item>
<Item>3</Item>
</ZenMenu>
</div>
<div className="Menu__item">
<ZenMenu
trigger={({ ref }) => (
<img
ref={ref}
width={30}
height={30}
src={notifications}
alt="Notifications"
/>
)}
>
<Item>1</Item>
<Item>2</Item>
<Item>3</Item>
</ZenMenu>
</div>
<div className="Menu__item">
<ZenMenu
trigger={({ ref }) => (
<Avatar innerRef={ref}>
<img src={avatar} alt="Joe Bloggs" />
</Avatar>
)}
>
<Item>Your Profile</Item>
<Item>Settings</Item>
<Item>About MoodleNet</Item>
<Item>Sign out</Item>
</ZenMenu>
</div>
</div>
);
interface MenuContainerProps {
show?: boolean;
open?: boolean;
}
const MenuContainer = styled.div`
order: 3;
max-width: 300px;
width: ${(props: MenuContainerProps) => (props.open ? '25%' : '0%')};
`;
const MenuNav = styled.ul`
position: fixed;
top: 0;
right: 0;
list-style-type: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
`;
const MenuNavItem = styled.li``;
const MenuBody = styled.div``;
interface MenuProps {
show?: boolean;
}
interface MenuState {
openMenuName: string | null;
open: boolean;
}
export default class extends React.Component<MenuProps, MenuState> {
static state = {
openMenuName: null,
open: false
};
constructor(props: MenuProps) {
super(props);
this.toggleMenu = this.toggleMenu.bind(this);
}
toggleMenu(menuName) {
if (this.state.openMenuName === menuName) {
this.setState({
openMenuName: null,
open: false
});
}
this.setState({
openMenuName: menuName,
open: true
});
}
render() {
return (
<MenuContainer show={this.props.show} open={this.state.open}>
<MenuNav>
<MenuNavItem onClick={() => this.toggleMenu('Search')}>
<img width={30} height={30} src={search} alt="Search" />
</MenuNavItem>
<MenuNavItem>
<ZenMenu
trigger={({ ref }) => (
<img
ref={ref}
width={30}
height={30}
src={notifications}
alt="Notifications"
/>
)}
>
<Item>1</Item>
<Item>2</Item>
<Item>3</Item>
</ZenMenu>
</MenuNavItem>
<MenuNavItem>
<ZenMenu
trigger={({ ref }) => (
<Avatar innerRef={ref}>
<img src={avatar} alt="Joe Bloggs" />
</Avatar>
)}
>
<Item>Your Profile</Item>
<Item>Settings</Item>
<Item>About MoodleNet</Item>
<Item>Sign out</Item>
</ZenMenu>
</MenuNavItem>
</MenuNav>
<MenuBody>menu body</MenuBody>
</MenuContainer>
);
}
}
import * as React from 'react';
import { Button as ZenButton } from '@zendeskgarden/react-buttons';
interface ButtonProps {
......@@ -21,6 +20,9 @@ interface ButtonProps {
selected?: boolean;
size?: 'small' | 'large';
stretched?: boolean;
type?: string;
style?: object;
title?: string;
}
const Button: React.SFC<ButtonProps> = ({
......
import * as React from 'react';
export default function({ flag }) {
return <div className={`flag-icon flag-icon-${flag}`} />;
}
import * as React from 'react';
export default () => {
return (
<div className="spinner">
<div className="bounce1" />
<div className="bounce2" />
<div className="bounce3" />
</div>
);
};
```js
<Checkbox /> unchecked
<Checkbox checked /> checked
```
import * as React from 'react';
import { Checkbox as ZenCheckbox } from '@zendeskgarden/react-checkboxes';
export default function Checkbox({ ...props }) {
return <ZenCheckbox {...props} />;
}
import * as React from 'react';
import {
SelectField as ZenSelectField,
Select,
Item
} from '@zendeskgarden/react-select';
import styled from '../../../themes/styled';
import Flag from '../../elements/Flag/Flag';
type LanguageSelectState = {
selectedKey?: string;
};
const SelectField = styled(ZenSelectField)`
max-width: 300px;
`;
const options = [
<Item key="en-gb">
<Flag flag="gb" />
&nbsp; English, United Kingdom
</Item>,
<Item key="en-us">
<Flag flag="us" />
&nbsp; English, United States
</Item>
];
/**
* TODO this is a dummy implementation of localisation toggling
*/
export default class extends React.Component<{}, LanguageSelectState> {
state = {
selectedKey: 'en-gb'
};
constructor(props) {
super(props);
}
render() {
return (
<SelectField>
<Select
selectedKey={this.state.selectedKey}
onChange={selectedKey => this.setState({ selectedKey })}
options={options}
>
<Flag flag={this.state.selectedKey.split('-')[1]} />
&nbsp;&nbsp;
{this.state.selectedKey}
</Select>
</SelectField>
);
}
}
import * as React from 'react';
const { Input } = require('@zendeskgarden/react-textfields');
import { Input } from '@zendeskgarden/react-textfields';
export default function Text({ ...props }) {
return <Input {...props} />;
......
......@@ -4,6 +4,7 @@ import { XXXL } from '@zendeskgarden/react-typography';
export interface HeadingProps {
children?: any;
tag?: string;
style?: object;
}
const H1 = ({ children, tag = 'h1', ...props }: HeadingProps) => {
......
import * as React from 'react';
export default function P({ children }) {
return <p>{children}</p>;
export default function({ children, ...props }) {
return <p {...props}>{children}</p>;
}
import * as React from 'react';
import { ApolloProvider } from 'react-apollo';
import styled from '../../themes/styled';
import Router from './Router';
import apolloClient from '../../apollo/client';
import { moodlenet } from '../../themes';
import { ThemeProvider } from '@zendeskgarden/react-theming';
import { Chrome } from '@zendeskgarden/react-chrome';
import '@zendeskgarden/react-chrome/dist/styles.css';
import '@zendeskgarden/react-grid/dist/styles.css';
import '@zendeskgarden/react-buttons/dist/styles.css';
......@@ -6,14 +15,11 @@ import '@zendeskgarden/react-menus/dist/styles.css';
import '@zendeskgarden/react-avatars/dist/styles.css';
import '@zendeskgarden/react-textfields/dist/styles.css';
import '@zendeskgarden/react-tags/dist/styles.css';
import '@zendeskgarden/react-select/dist/styles.css';
import Nav from '../../components/chrome/Nav/Nav';
import CommunitiesFeatured from '../../pages/communities.featured/CommunitiesFeatured';
import Menu from '../../components/chrome/Menu/Menu';
import styled from '../../themes/styled';
import { moodlenet } from '../../themes';
const { ThemeProvider } = require('@zendeskgarden/react-theming');
const { Chrome, Body } = require('@zendeskgarden/react-chrome');
import '../../styles/social-icons.css';
import '../../styles/flag-icons.css';
import '../../styles/loader.css';
export const AppStyles = styled.div`
font-family: ${props => props.theme.styles.fontFamily};
......@@ -22,17 +28,15 @@ export const AppStyles = styled.div`
export default class App extends React.Component {
render() {
return (
<ThemeProvider theme={moodlenet}>
<AppStyles>
<Chrome>
<Nav />
<Body>
<Menu />
<CommunitiesFeatured />
</Body>
</Chrome>
</AppStyles>
</ThemeProvider>
<ApolloProvider client={apolloClient}>
<ThemeProvider theme={moodlenet}>
<AppStyles>
<Chrome>
<Router />
</Chrome>
</AppStyles>
</ThemeProvider>
</ApolloProvider>
);
}
}
Supports Markdown
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