Skip to content

Commit

Permalink
Merge pull request #16 from openwisp/frontend
Browse files Browse the repository at this point in the history
Add header, footer, registration component
  • Loading branch information
Vivekrajput20 committed Jul 15, 2019
2 parents bc3bce6 + 92c1a67 commit c2fca2e
Show file tree
Hide file tree
Showing 51 changed files with 2,382 additions and 141 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ yarn-error.log*
#other
/org-configurations
client/config.json
client/assets/
server/config.json
1 change: 1 addition & 0 deletions __mocks__/fileMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = "test-file-stub";
1 change: 1 addition & 0 deletions __mocks__/styleMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {};
66 changes: 66 additions & 0 deletions client/actions/actions.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import merge from "deepmerge";
import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk";

import * as types from "../constants/action-types";
import testOrgConfig from "../test-config.json";
import parseOrganizations from "./parse-organizations";
import setLanguage from "./set-language";
import setOrganization from "./set-organization";

jest.mock("../utils/get-config");
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

describe("actions testing", () => {
it("should create an action to parse organizations", () => {
const expectedActions = [
{
type: types.PARSE_ORGANIZATIONS,
payload: testOrgConfig,
},
];
const store = mockStore({organizations: []});
store.dispatch(parseOrganizations(testOrgConfig));
expect(store.getActions()).toEqual(expectedActions);
});

it("should create an action to set language", () => {
const language = "en";
const expectedActions = [
{
type: types.SET_LANGUAGE,
payload: language,
},
];
const store = mockStore({language: ""});
store.dispatch(setLanguage(language));
expect(store.getActions()).toEqual(expectedActions);
});

it("should create actions to set current organization", () => {
const orgConfig = merge(testOrgConfig[0], testOrgConfig[2]);
const expectedActions = [
{
type: types.SET_LANGUAGE,
payload: testOrgConfig[0].default_language,
},
{
type: types.SET_ORGANIZATION_STATUS,
payload: true,
},
{
type: types.SET_ORGANIZATION_CONFIG,
payload: orgConfig,
},
{
type: types.SET_ORGANIZATION_STATUS,
payload: false,
},
];
const store = mockStore({language: "", organization: {}});
store.dispatch(setOrganization(testOrgConfig[2].slug));
store.dispatch(setOrganization("invalid-slug"));
expect(store.getActions()).toEqual(expectedActions);
});
});
9 changes: 9 additions & 0 deletions client/actions/parse-organizations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {PARSE_ORGANIZATIONS} from "../constants/action-types";

const parseOrganizations = config => {
return {
type: PARSE_ORGANIZATIONS,
payload: config,
};
};
export default parseOrganizations;
10 changes: 10 additions & 0 deletions client/actions/set-language.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {SET_LANGUAGE} from "../constants/action-types";

const setLanguage = slug => {
return {
type: SET_LANGUAGE,
payload: slug,
};
};

export default setLanguage;
39 changes: 39 additions & 0 deletions client/actions/set-organization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import merge from "deepmerge";

import {
SET_LANGUAGE,
SET_ORGANIZATION_CONFIG,
SET_ORGANIZATION_STATUS,
} from "../constants/action-types";
import customMerge from "../utils/custom-merge";
import getConfig from "../utils/get-config";

const setOrganization = slug => {
return dispatch => {
const orgConfig = getConfig(slug);
if (orgConfig) {
const defaultConfig = getConfig("default");
const config = merge(defaultConfig, orgConfig, {
arrayMerge: customMerge,
});
dispatch({
type: SET_LANGUAGE,
payload: config.default_language,
});
dispatch({
type: SET_ORGANIZATION_STATUS,
payload: true,
});
dispatch({
type: SET_ORGANIZATION_CONFIG,
payload: config,
});
} else {
dispatch({
type: SET_ORGANIZATION_STATUS,
payload: false,
});
}
};
};
export default setOrganization;
19 changes: 19 additions & 0 deletions client/components/404/404.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import "./index.css";

import React from "react";

export default class DoesNotExist extends React.Component {
render() {
return (
<React.Fragment>
<div className="owisp-404-container">
<div className="owisp-404-row-1">Oops!</div>
<div className="owisp-404-row-2">404 Not Found</div>
<div className="owisp-404-row-3">
Sorry, an error has occurred, Requested page not found!
</div>
</div>
</React.Fragment>
);
}
}
11 changes: 11 additions & 0 deletions client/components/404/404.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from "react";
import renderer from "react-test-renderer";

import DoesNotExist from "./404";

describe("<DoesNotExist /> rendering", () => {
it("should render correctly", () => {
const component = renderer.create(<DoesNotExist />).toJSON();
expect(component).toMatchSnapshot();
});
});
23 changes: 23 additions & 0 deletions client/components/404/__snapshots__/404.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<DoesNotExist /> rendering should render correctly 1`] = `
<div
className="owisp-404-container"
>
<div
className="owisp-404-row-1"
>
Oops!
</div>
<div
className="owisp-404-row-2"
>
404 Not Found
</div>
<div
className="owisp-404-row-3"
>
Sorry, an error has occurred, Requested page not found!
</div>
</div>
`;
27 changes: 27 additions & 0 deletions client/components/404/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.owisp-404-container {
background: #f5f5f5;
color: #333;
width: 100%;
height: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 500;
line-height: 1.1;
}
.owisp-404-row-1 {
font-size: 36px;
}
.owisp-404-row-2 {
font-size: 30px;
margin-top: 20px;
margin-bottom: 10px;
}
.owisp-404-row-3 {
font-size: 14px;
font-weight: normal;
line-height: 1.4;
}
8 changes: 8 additions & 0 deletions client/components/404/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {connect} from "react-redux";

import Component from "./404";

export default connect(
null,
null,
)(Component);
43 changes: 43 additions & 0 deletions client/components/footer/__snapshots__/footer.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Footer /> rendering should render correctly 1`] = `
<div
className="owisp-footer-container"
>
<div
className="owisp-footer-row-1"
>
<div
className="owisp-footer-row-1-inner"
>
<a
className="owisp-footer-link
owisp-footer-link-1"
href="www.testurl.com"
rel="noreferrer noopener"
target="_blank"
>
link one
</a>
<a
className="owisp-footer-link
owisp-footer-link-2"
href="www.testurl2.com"
rel="noreferrer noopener"
target="_blank"
>
link two
</a>
</div>
</div>
<div
className="owisp-footer-row-2"
>
<div
className="owisp-footer-row-2-inner"
>
this is secondary text
</div>
</div>
</div>
`;
51 changes: 51 additions & 0 deletions client/components/footer/footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import "./index.css";

import PropTypes from "prop-types";
import React from "react";

import getText from "../../utils/get-text";

export default class Footer extends React.Component {
render() {
const {footer, language} = this.props;
const {links} = footer;
const secondaryText = footer.secondary_text;
return (
<React.Fragment>
<div className="owisp-footer-container">
<div className="owisp-footer-row-1">
<div className="owisp-footer-row-1-inner">
{links.map((link, index) => {
return (
<a
href={link.url}
className={`owisp-footer-link
owisp-footer-link-${index + 1}`}
target="_blank"
rel="noreferrer noopener"
key={link.url}
>
{getText(link.text, language)}
</a>
);
})}
</div>
</div>
<div className="owisp-footer-row-2">
<div className="owisp-footer-row-2-inner">
{getText(secondaryText, language)}
</div>
</div>
</div>
</React.Fragment>
);
}
}

Footer.propTypes = {
language: PropTypes.string.isRequired,
footer: PropTypes.shape({
links: PropTypes.array,
secondary_text: PropTypes.object,
}).isRequired,
};
56 changes: 56 additions & 0 deletions client/components/footer/footer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* eslint-disable camelcase */
import {shallow} from "enzyme";
import React from "react";
import renderer from "react-test-renderer";

import Footer from "./footer";

const createTestProps = props => {
return {
language: "en",
footer: {
links: [
{
text: {en: "link one"},
url: "www.testurl.com",
},
{
text: {en: "link two"},
url: "www.testurl2.com",
},
],
secondary_text: {
en: "this is secondary text",
},
},
...props,
};
};

describe("<Footer /> rendering", () => {
let props;
let wrapper;
beforeEach(() => {
props = createTestProps();
wrapper = shallow(<Footer {...props} />);
});
it("should render correctly", () => {
props = createTestProps();
const component = renderer.create(<Footer {...props} />).toJSON();
expect(component).toMatchSnapshot();
});
it("should render without links", () => {
const links = {
footer: {...props.footer, links: []},
};
props = createTestProps(links);
wrapper = shallow(<Footer {...props} />);
expect(wrapper.find(".owisp-footer-link")).toHaveLength(0);
});
it("should render secondary text", () => {
const {secondary_text} = props.footer;
expect(wrapper.find(".owisp-footer-row-2-inner").text()).toBe(
secondary_text.en,
);
});
});
Loading

0 comments on commit c2fca2e

Please sign in to comment.