박선진

delete unnecessary codes from template code

Showing 415 changed files with 20 additions and 4784 deletions
......@@ -15,6 +15,7 @@
.env.development.local
.env.test.local
.env.production.local
.env
npm-debug.log*
yarn-debug.log*
......
This diff could not be displayed because it is too large.
......@@ -61,14 +61,12 @@
"bootstrap_calendar": "https://github.com/xero/bootstrap_calendar.git#1.0.1",
"classnames": "^2.2.6",
"draft-js": "^0.10.5",
"easy-pie-chart": "^2.1.7",
"flot": "^0.8.0-alpha",
"flot.dashes": "https://github.com/cquartier/flot.dashes.git",
"font-awesome": "4.7.0",
"formsy-react": "0.19.5",
"fullcalendar": "^3.9.0",
"glyphicons-halflings": "^1.9.1",
"govpredict-morris": "0.5.1",
"jasny-bootstrap": "^3.1.3",
"jquery": "^3.3.1",
"jquery-mapael": "^2.2.0",
......@@ -83,7 +81,10 @@
"messenger": "git+https://github.com/HubSpot/messenger.git#v1.4.2",
"metrojs": "0.9.77",
"moment": "^2.22.2",
"moment-timezone": "^0.5.26",
"nvd3": "1.8.6",
"pretty": "^2.0.0",
"prettysize": "^2.0.0",
"rc-color-picker": "^1.2.6",
"rc-hammerjs": "0.6.9",
"react": "^16.5.2",
......@@ -107,6 +108,7 @@
"react-router-dom": "^4.3.1",
"react-router-hash-link": "^1.2.1",
"react-scrollspy": "^3.3.5",
"react-select": "^3.0.4",
"react-select2-wrapper": "^1.0.4-beta6",
"react-shuffle": "2.1.0",
"react-slick": "^0.23.1",
......@@ -122,9 +124,11 @@
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"rickshaw": "1.6.6",
"semantic-ui-react": "^0.87.3",
"showdown": "1.8.6",
"skycons": "^1.0.0",
"widgster": "^1.0.0"
"widgster": "^1.0.0",
"xlsx": "^0.14.4"
},
"devDependencies": {
"@babel/core": "7.4.4",
......@@ -140,10 +144,10 @@
"bfj": "6.1.1",
"bundle-loader": "0.5.6",
"case-sensitive-paths-webpack-plugin": "2.2.0",
"chalk": "2.4.2",
"chalk": "^2.4.2",
"css-loader": "2.1.1",
"dotenv": "8.0.0",
"dotenv-expand": "5.1.0",
"dotenv": "^8.2.0",
"dotenv-expand": "^5.1.0",
"eslint": "5.16.0",
"eslint-config-react-app": "4.0.1",
"eslint-loader": "2.1.1",
......@@ -175,7 +179,7 @@
"style-loader": "0.23.0",
"terser-webpack-plugin": "1.2.3",
"url-loader": "1.1.2",
"webpack": "4.31.0",
"webpack": "^4.31.0",
"webpack-dev-server": "3.3.1",
"webpack-manifest-plugin": "2.0.4",
"webpack-raphael": "2.1.4",
......

10.4 KB | W: | H:

12 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
<?php sleep(10) ?>
<h3 class="text-center no-margin animated bounceInDown">Sign up, <del>it's <strong>free</strong></del> and get <strong>$50 now!</strong></h3>
<p class="lead text-muted text-center">
Faith makes it possible to achieve that which man's mind can conceive and believe.
</p>
<form>
<div class="form-group">
<label for="exampleInputEmail1"><i class="fa fa-circle text-warning"></i> &nbsp; Email address</label>
<input type="email" class="form-control input-transparent" id="exampleInputEmail1"
placeholder="Enter email">
</div>
<div class="form-group">
<label for="pswd"><i class="fa fa-circle text-danger"></i> &nbsp; Password</label>
<input class="form-control" id="pswd" type="text" placeholder="Min 8 characters">
</div>
<p>
To make a widget automatically load it's content you just need to set
<strong>data-widgster-autoload</strong> attribute and provide an url.
</p>
<pre><code>data-widgster-load="server/ajax_widget.php"
data-widgster-autoload="true"</code></pre>
<p>
<strong>data-widgster-autoload</strong> may be set to an integer value. If set, for example, to
2000 will refresh widget every 2 seconds.
</p>
<div class="clearfix">
<div class="btn-toolbar float-right">
<button type="submit" class="btn btn-transparent">Cancel</button>
<button type="submit" class="btn btn-success animated wobble">&nbsp;Submit&nbsp;</button>
</div>
</div>
</form>
<!-- demo latetency <?php sleep(2) ?> -->
<p class="text-muted">Simulating latency with tiny php block on the server-side.</p>
<p>A timestamp this widget was created: Apr 24, 19:07:07</p>
<p>A timestamp this widget was updated: <?php echo date("M j, H:i:s") ?></p>
\ No newline at end of file
<!-- <?php sleep(2) //just some delay to simulate latency ?> -->
<ul class="news-list stretchable">
<li class="animated fadeInDown bg-warning-light">
<span class="icon bg-warning text-white">
<i class="fa fa-lock"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">Just now! Check update time</a></h5>
<p class="fs-mini">
Check this news item timestamp. There is a small server part that generates current timestamp so it
would be easier for you to see ajax widgets in action
</p>
<time class="help-block"><?php echo date("M j, H:i:s")?></time>
</div>
</li>
<li>
<span class="icon bg-danger text-white">
<i class="fa fa-star"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">First Human Colony on Mars</a></h5>
<p class="fs-mini">
First 700 people will take part in building first human settlement outside of Earth.
That's awesome, right?
</p>
<time class="help-block">Mar 20, 18:46</time>
</div>
</li>
<li>
<span class="icon bg-info text-white">
<i class="fa fa-microphone"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">Light Blue reached $300</a></h5>
<p class="fs-mini">
Light Blue Inc. shares just hit $300 price. "This was inevitable. It should
have happen sooner or later" - says NYSE expert.
</p>
<time class="help-block">Sep 25, 11:59</time>
</div>
</li>
<li>
<span class="icon bg-success text-white">
<i class="fa fa-eye"></i>
</span>
<div class="news-item-info">
<h5 class="name no-margin mb-xs"><a href="#">No more spying</a></h5>
<p class="fs-mini">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</p>
<time class="help-block">Mar 20, 18:46</time>
</div>
</li>
</ul>
<?php sleep(2) ?>
<div class="list-group list-group-lg">
<a href="#" class="list-group-item animated fadeInDown bg-warning-light">
<span class="thumb-sm mr">
<img class="rounded-circle" src="/images/people/a6.jpg" alt="...">
</span>
<div>
<h6 class="no-margin"><strong>Jenny Wilington</strong></h6>
<small>just now</small>
</div>
<i class="fa fa-circle ml-auto text-success mt-sm"></i>
</a>
<a href="#" class="list-group-item ">
<span class="thumb-sm mr">
<img class="rounded-circle" src="/images/people/a1.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Maikel Basso</h6>
<small class="text-muted">about 2 mins ago</small>
</div>
<i class="fa fa-circle ml-auto text-danger"></i>
</a>
<a href="#" class="list-group-item">
<span class="thumb-sm mr">
<img class="rounded-circle" src="/images/people/a2.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Ianus Arendse</h6>
<small class="text-muted">about 42 mins ago</small>
</div>
<i class="fa fa-circle ml-auto text-info"></i>
</a>
<a href="#" class="list-group-item">
<span class="thumb-sm mr">
<img class="rounded-circle" src="/images/people/a3.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Valdemar Landau</h6>
<small class="text-muted">one hour ago</small>
</div>
<i class="fa fa-circle ml-auto text-success"></i>
</a>
<a href="#" class="list-group-item mb-n-md">
<span class="thumb-sm mr">
<img class="rounded-circle" src="/images/people/a4.jpg" alt="...">
</span>
<div>
<h6 class="m-0">Rick Teagan</h6>
<small class="text-muted">3 hours ago</small>
</div>
<i class="fa fa-circle ml-auto text-warning"></i>
</a>
</div>

5.18 KB | W: | H:

12 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
......@@ -19,7 +19,7 @@
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`.
-->
<title>Sing App React Dashboard - Admin Template built with React</title>
<title>Video Emergency Detection</title>
<meta name="description" content="React Admin Dashboard Template built with Bootstrap, Redux and React Router by Flatlogic. Over 40 unique pages, hundreds of components and theme support.">
<meta name="keywords" content="react admin, react dashboard, react admin template, react theme, react dashboard template, react dashboard template">
<meta name="author" content="Flatlogic LLC.">
......
export const DISMISS_ALERT = 'DISMISS_ALERT';
export function dismissAlert(id) {
return {
type: DISMISS_ALERT,
id,
};
}
import axios from 'axios';
export const RECEIVED_DATA_SUCCESS = 'RECEIVED_DATA_SUCCESS';
export const RECEIVING_DATA = 'RECEIVING_DATA';
export function receiveDataRequest() {
return (dispatch) => {
dispatch(receivingData());
axios.get('/analytics').then(res => {
dispatch(receiveDataSuccess(res.data));
})
};
}
export function receiveDataSuccess(payload) {
return {
type: RECEIVED_DATA_SUCCESS,
payload
}
}
export function receivingData() {
return {
type: RECEIVING_DATA
}
}
import axios from 'axios';
import { toast } from 'react-toastify';
export const RECEIVED_PRODUCTS = 'RECEIVED_PRODUCTS';
export const RECEIVING_PRODUCTS = 'RECEIVING_PRODUCTS';
export const RECEIVED_PRODUCT = 'RECEIVED_PRODUCT';
export const RECEIVING_PRODUCT = 'RECEIVING_PRODUCT';
export const UPDATED_PRODUCT = 'UPDATED_PRODUCT';
export const UPDATING_PRODUCT = 'UPDATING_PRODUCT';
export const DELETED_PRODUCT = 'DELETED_PRODUCT';
export const DELETING_PRODUCT = 'DELETING_PRODUCT';
export const RECEIVED_IMAGES = 'RECEIVED_IMAGES';
export function getProductsRequest() {
return (dispatch) => {
dispatch(receivingProducts());
axios.get('/products').then(res => {
dispatch(receiveProducts(res.data));
})
};
}
export function loadProductRequest(id) {
return (dispatch) => {
dispatch(receivingProduct());
axios.get('/products/' + id).then(res => {
dispatch(receiveProduct(res.data));
})
};
}
export function updateProductRequest(product) {
return (dispatch) => {
dispatch(updatingProduct());
axios.put('/products/' + product.id, product).then(res => {
dispatch(updateProduct(res.data));
toast.success("Product has been Updated!");
})
};
}
export function createProductRequest(payload) {
return (dispatch) => {
dispatch(updatingProduct());
axios.post('/products', payload.product).then(res => {
dispatch(updateProduct(res.data));
payload.history.push('/app/ecommerce/management');
toast.success("Product has been Created!");
})
};
}
export function deleteProductRequest(payload) {
return (dispatch) => {
dispatch(deletingProduct(payload));
axios.delete('/products/' + payload.id).then(res => {
dispatch(deleteProduct({id: payload.id}));
if (payload.history.location.pathname !== '/app/ecommerce/management') {
payload.history.push('/app/ecommerce/management');
}
toast.success("Product has been Deleted!");
})
};
}
export function getProductsImagesRequest(payload) {
return (dispatch) => {
axios.get('/products/images-list').then(res => {
dispatch(receiveProductImages(res.data));
if (!payload.img && res.data.length) {
dispatch(updateProduct({id: payload.id, img: res.data[0]}));
}
})
};
}
export function receiveProductImages(payload) {
return {
type: RECEIVED_IMAGES,
payload
}
}
export function receiveProducts(payload) {
return {
type: RECEIVED_PRODUCTS,
payload
}
}
export function receivingProducts() {
return {
type: RECEIVING_PRODUCTS
}
}
export function receiveProduct(payload) {
return {
type: RECEIVED_PRODUCT,
payload
}
}
export function receivingProduct() {
return {
type: RECEIVING_PRODUCT
}
}
export function updateProduct(payload) {
return {
type: UPDATED_PRODUCT,
payload
}
}
export function updatingProduct() {
return {
type: UPDATING_PRODUCT
}
}
export function deleteProduct(payload) {
return {
type: DELETED_PRODUCT,
payload
}
}
export function deletingProduct(payload) {
return {
type: DELETING_PRODUCT,
payload
}
}
import axios from 'axios';
import { toast } from 'react-toastify';
export const REGISTER_REQUEST = 'REGISTER_REQUEST';
export const REGISTER_SUCCESS = 'REGISTER_SUCCESS';
export const REGISTER_FAILURE = 'REGISTER_FAILURE';
function requestRegister() {
return {
type: REGISTER_REQUEST,
};
}
export function receiveRegister() {
return {
type: REGISTER_SUCCESS
};
}
export function registerError(payload) {
return {
type: REGISTER_FAILURE,
payload,
};
}
export function registerUser(payload) {
return (dispatch) => {
dispatch(requestRegister());
debugger;
const creds = payload.creds;
if (creds.email.length > 0 && creds.password.length > 0) {
axios.post("/user/signup", creds).then(res => {
dispatch(receiveRegister());
toast.success("You've been registered successfully");
payload.history.push('/login');
}).catch(err => {
dispatch(registerError(err.response.data));
})
} else {
dispatch(registerError('Something was wrong. Try again'));
}
};
}
import axios from 'axios';
import config from '../config';
import jwt from "jsonwebtoken";
export const LOGIN_REQUEST = 'LOGIN_REQUEST';
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
export const LOGIN_FAILURE = 'LOGIN_FAILURE';
export const LOGOUT_REQUEST = 'LOGOUT_REQUEST';
export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
export const LOGOUT_FAILURE = 'LOGOUT_FAILURE';
function requestLogin() {
return {
type: LOGIN_REQUEST,
};
}
export function receiveLogin() {
return {
type: LOGIN_SUCCESS
};
}
function loginError(payload) {
return {
type: LOGIN_FAILURE,
payload,
};
}
function requestLogout() {
return {
type: LOGOUT_REQUEST,
};
}
export function receiveLogout() {
return {
type: LOGOUT_SUCCESS,
};
}
// Logs the user out
export function logoutUser() {
return (dispatch) => {
dispatch(requestLogout());
localStorage.removeItem('token');
localStorage.removeItem('user');
document.cookie = 'token=;expires=Thu, 01 Jan 1970 00:00:01 GMT;';
axios.defaults.headers.common['Authorization'] = "";
dispatch(receiveLogout());
};
}
export function receiveToken(token) {
return (dispatch) => {
let user = jwt.decode(token).user;
delete user.id;
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
axios.defaults.headers.common['Authorization'] = "Bearer " + token;
dispatch(receiveLogin());
}
}
export function loginUser(creds) {
return (dispatch) => {
dispatch(requestLogin());
if (creds.social) {
window.location.href = config.baseURLApi + "/user/signin/" + creds.social + (process.env.NODE_ENV === "production" ? "?app=sing-app-react" : "");
}
else if (creds.email.length > 0 && creds.password.length > 0) {
axios.post("/user/signin/local", creds).then(res => {
const token = res.data.token;
dispatch(receiveToken(token));
}).catch(err => {
dispatch(loginError(err.response.data));
})
} else {
dispatch(loginError('Something was wrong. Try again'));
}
};
}
......@@ -10,21 +10,6 @@ import ErrorPage from '../pages/error';
import '../styles/theme.scss';
import LayoutComponent from '../components/Layout';
import DocumentationLayoutComponent from '../documentation/DocumentationLayout';
import Login from '../pages/login';
import Register from '../pages/register';
import { logoutUser } from '../actions/user';
const PrivateRoute = ({dispatch, component, ...rest }) => {
if (!Login.isAuthenticated(localStorage.getItem('token'))) {
dispatch(logoutUser());
return (<Redirect to="/login"/>)
} else {
return ( // eslint-disable-line
<Route {...rest} render={props => (React.createElement(component, props))}/>
);
}
};
const CloseButton = ({closeToast}) => <i onClick={closeToast} className="la la-close notifications-close"/>
......@@ -41,14 +26,9 @@ class App extends React.PureComponent {
<Switch>
<Route path="/" exact render={() => <Redirect to="/app/main"/>}/>
<Route path="/app" exact render={() => <Redirect to="/app/main"/>}/>
<PrivateRoute path="/app" dispatch={this.props.dispatch} component={LayoutComponent}/>
<Route path="/documentation" exact
render={() => <Redirect to="/documentation/getting-started/overview"/>}/>
<Route path="/documentation" component={DocumentationLayoutComponent}/>
<Route path="/register" exact component={Register}/>
<Route path="/login" exact component={Login}/>
<Route path="/app" component={LayoutComponent}/>
<Route path="/error" exact component={ErrorPage}/>
<Redirect from="*" to="/app/main/analytics"/>
<Redirect from="*" to="/app/main/"/>
</Switch>
</HashRouter>
</div>
......@@ -58,7 +38,6 @@ class App extends React.PureComponent {
}
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
});
export default connect(mapStateToProps)(App);
......
import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import { ListGroup, ListGroupItem, InputGroup, InputGroupAddon, Input, InputGroupText } from 'reactstrap';
import $ from 'jquery';
import * as a1 from '../../images/people/a1.jpg';
import * as a2 from '../../images/people/a2.jpg';
import * as a3 from '../../images/people/a3.jpg';
import * as a4 from '../../images/people/a4.jpg';
import * as a5 from '../../images/people/a5.jpg';
import * as a6 from '../../images/people/a6.jpg';
import * as avatar from '../../images/avatar.png';
import s from './Chat.module.scss';
class Chat extends React.Component {
static propTypes = {
chatOpen: PropTypes.bool,
};
static defaultProps = {
chatOpen: false,
};
constructor(props) {
super(props);
this.handleChangeContacts = this.handleChangeContacts.bind(this);
this.openMessages = this.openMessages.bind(this);
this.filterConversations = this.filterConversations.bind(this);
this.filterMessages = this.filterMessages.bind(this);
this.addMessage = this.addMessage.bind(this);
this.state = {
todayConversations: [{
name: 'Chris Gray',
status: 'success',
lastMessage: 'Hey! What\'s up? So many times since we',
image: a2,
messages: [{
id: 0,
text: 'Hey! What\'s up?',
}, {
id: 1,
text: 'Are you there?',
}, {
id: 2,
text: 'Let me know when you come back.',
}, {
id: 3,
text: 'I am here!',
fromMe: true,
}],
}, {
name: 'Jamey Brownlow',
status: 'gray-light',
lastMessage: 'Good news coming tonight. Seems they agreed to proceed',
image: avatar,
}, {
name: 'Livia Walsh',
status: 'danger',
lastMessage: 'Check out my latest email plz!',
image: a1,
}, {
name: 'Jaron Fitzroy',
status: 'gray-light',
lastMessage: 'What about summer break?',
image: avatar,
}, {
name: 'Mike Lewis',
status: 'success',
lastMessage: 'Just ain\'t sure about the weekend now. 90% I\'ll make it.',
image: a4,
}],
lastWeekConversations: [{
name: 'Freda Edison',
status: 'gray-light',
lastMessage: 'Hey what\'s up? Me and Monica going for a lunch somewhere. Wanna join?',
image: a6,
}, {
name: 'Livia Walsh',
status: 'success',
lastMessage: 'Check out my latest email plz!',
image: a5,
}, {
name: 'Jaron Fitzroy',
status: 'warning',
lastMessage: 'What about summer break?',
image: a3,
}, {
name: 'Mike Lewis',
status: 'gray-light',
lastMessage: 'Just ain\'t sure about the weekend now. 90% I\'ll make it.',
image: avatar,
}],
chatMessageOpened: true,
conversation: Object,
searchValue: '',
};
}
openMessages(conversation, e) {
this.setState({
conversation,
chatMessageOpened: false,
});
$(e.currentTarget).removeClass('active').find('.badge').remove();
}
addMessage(e) {
if (e.key === 'Enter') {
const value = {
text: e.target.value,
fromMe: true,
};
this.setState({
conversation: Object.assign({}, this.state.conversation, {
messages: [
...this.state.conversation.messages || [],
value,
],
}),
});
e.target.value = ''; // eslint-disable-line
}
}
handleChangeContacts(event) {
this.setState({ searchValue: event.target.value });
}
filterConversations(item) {
const isFindName = item.name.toLowerCase()
.indexOf(this.state.searchValue.toLowerCase()) !== -1;
const isFindMessage = item.lastMessage.toLowerCase()
.indexOf(this.state.searchValue.toLowerCase()) !== -1;
return isFindName || isFindMessage;
}
filterMessages(item) {
return item.text.toLowerCase().indexOf(this.state.searchValue.toLowerCase()) !== -1;
}
render() {
return (
<aside className={[s.root, this.props.chatOpen ? s.chatOpen : ''].join(' ')}>
<header className={s.chatHeader}>
<h4 className={s.chatTitle}>Contacts</h4>
<div className="input-group input-group-transparent">
<InputGroup size="sm">
<Input placeholder="Search..." value={this.state.searchValue} onChange={this.handleChangeContacts} />
<InputGroupAddon addonType="append">
<InputGroupText>
<i className="fa fa-search"/>
</InputGroupText>
</InputGroupAddon>
</InputGroup>
</div>
</header>
<div className={[s.chatPanel, s.chatContacts, this.state.chatMessageOpened ? s.chatMessageOpen : ''].join(' ')}>
<h5 className={s.navTitle}>TODAY</h5>
<ListGroup id="chat-sidebar-user-group" className={s.chatSidebarUserGroup}>
{this.state.todayConversations
.filter(this.filterConversations)
.map(item =>
<ListGroupItem
key={item.name}
onClick={e => this.openMessages(item, e)}
>
<i className={['fa fa-circle float-right', `text-${item.status}`].join(' ')} />
<span className="thumb-sm float-left mr">
<img className="rounded-circle" src={item.image} alt="..." />
</span>
<div>
<h6 className={s.messageSender}>{item.name}</h6>
<p className={s.messagePreview}>{item.lastMessage}</p>
</div>
</ListGroupItem>,
)}
</ListGroup>
<h5 className={s.navTitle}>LAST WEEK</h5>
<ListGroup className={s.chatSidebarUserGroup}>
{this.state.lastWeekConversations
.filter(this.filterConversations)
.map(item =>
<ListGroupItem
key={item.name}
onClick={e => this.openMessages(item, e)}
>
<i className={['fa fa-circle float-right', `text-${item.status}`].join(' ')} />
<span className="thumb-sm pull-left mr">
<img className="rounded-circle" src={item.image} alt="..." />
</span>
<div>
<h6 className={s.messageSender}>{item.name}</h6>
<p className={s.messagePreview}>{item.lastMessage}</p>
</div>
</ListGroupItem>,
)}
</ListGroup>
</div>
<div className={[s.chatPanel, s.chatMessages, this.state.chatMessageOpened ? '' : s.chatMessageOpen].join(' ')}>
<h6 className={s.messagesTitle}>
{/* eslint-disable */}
<a onClick={() => this.setState({ chatMessageOpened: true })}>
<i className="fa fa-angle-left mr-xs" />
{this.state.conversation.name}
</a>
{/* eslint-disable */}
</h6>
<ListGroup>
{this.state.conversation.messages &&
this.state.conversation.messages
.filter(this.filterMessages)
.map(item => <ListGroupItem key={item.id} className={[item.fromMe ? s.fromMe : '', s.messageItem]}>
<span className="thumb-sm">
<img className="rounded-circle"
src={item.fromMe ? avatar : this.state.conversation.image} alt="..."/>
</span>
<div className={s.messageBody}>{item.text}</div>
</ListGroupItem>,
)}
</ListGroup>
<footer className={[s.chatFooter, 'form-group'].join(' ')}>
<input className="form-control fs-mini" onKeyPress={this.addMessage} type="text"
placeholder="Type your message"/>
</footer>
</div>
</aside>
);
}
}
export default withRouter(Chat);
@import '../../styles/app';
.root {
position: fixed;
overflow: hidden;
top: 0;
bottom: 0;
right: -$chat-sidebar-width-open;
width: $chat-sidebar-width-open;
border-left: $sidebar-border;
background-color: var(--chat-sidebar-bg-color);
color: #aaa;
transition: right 0.3s ease-in-out;
@include media-breakpoint-down(md) {
right: -($chat-sidebar-width-open + 25px);
width: $chat-sidebar-width-open + 25px;
}
&.chatOpen {
right: 0;
}
.chatHeader {
position: absolute;
width: 100%;
top: 0;
z-index: 3;
padding: 10px;
background-color: var(--chat-sidebar-bg-color);
input {
padding: 0.6rem 0.85rem;
line-height: 1.5;
}
.chatTitle {
margin: 10px;
text-transform: uppercase;
font-size: 15px;
font-weight: 400;
}
}
.chatPanel {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
:global .list-group-item {
border: 0;
padding: 10px 20px;
z-index: 1;
.cirle {
font-size: 11px;
line-height: 37px;
margin-left: auto;
}
}
.navTitle {
margin: 35px 10px 5px 20px;
font-size: 14px;
}
.navTitle:first-child {
margin-top: 0;
}
.messageSender {
text-overflow: ellipsis;
color: var(--sidebar-color);
}
.messagePreview {
margin: 0;
width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 85%;
color: #999;
}
}
.chatContacts {
padding-top: 105px;
left: -100%;
transition: left 0.2s ease-in-out;
:global .list-group {
margin-top: 10px;
:global .list-group-item {
cursor: pointer;
}
}
&.chatMessageOpen {
left: 0;
overflow-y: auto;
@include scroll-bar(rgba($white, 0.3));
}
}
.chatMessages {
padding-top: 100px;
right: -100%;
transition: right 0.2s ease-in-out;
background-color: var(--sidebar-bg-color);
:global .list-group {
position: absolute;
top: 134px; // header height
bottom: 47px; // footer height
width: 100%;
padding-top: 0.5rem;
overflow-y: auto;
@include scroll-bar(rgba($white, 0.3));
:global .list-group-item {
align-items: flex-start;
}
:global .thumb-sm {
float: left;
}
}
.messageBody {
position: relative;
margin-left: 50px;
padding: 10px;
font-size: 13px;
font-weight: $font-weight-normal;
background-color: $gray-200;
color: $text-color;
border-radius: 0.25rem;
&::before {
right: 100%;
top: 8px;
content: '';
height: 0;
width: 0;
position: absolute;
border: 10px solid rgba(0, 0, 0, 0);
border-right-color: $gray-200;
}
}
.fromMe {
flex-direction: row-reverse;
:global .thumb-sm {
float: right;
}
.messageBody {
margin-left: 0;
margin-right: 50px;
background-color: theme-color('warning');
color: $gray-800;
&::before {
right: auto;
left: 100%;
border-right-color: rgba(0, 0, 0, 0);
border-left-color: theme-color('warning');
}
}
}
.chatFooter {
position: absolute;
z-index: 1;
bottom: 0;
width: 100%;
margin-bottom: 0;
padding: 10px;
background-color: $white;
}
&.chatMessageOpen {
right: 0;
}
.messagesTitle {
margin-bottom: 0;
a {
display: block;
margin-top: -7px;
padding: 17px 16px;
}
}
}
.chatSidebarUserGroup {
:global .list-group-item {
transition: $transition-base;
}
:global .list-group-item.active {
background: rgba($white, 0.1);
}
:global .list-group-item.active h6 {
color: theme-color('warning');
font-weight: $badge-font-weight;
}
:global .list-group-item:hover {
background: var(--sidebar-action-bg);
}
:global .badge {
margin: 8px 5px 0 0;
padding: 3px 5px;
}
:global .fa {
margin-top: 11px;
}
}
.messageItem {
&:hover {
background: transparent;
}
}
}
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router';
import {
Navbar,
Nav,
Dropdown,
NavItem,
NavLink,
Badge,
DropdownToggle,
DropdownMenu,
DropdownItem,
UncontrolledTooltip,
InputGroupAddon,
InputGroup,
Input,
Form,
FormGroup,
} from 'reactstrap';
import $ from 'jquery';
import Notifications from '../Notifications';
import { logoutUser } from '../../actions/user';
import { toggleSidebar, openSidebar, closeSidebar, changeActiveSidebarItem } from '../../actions/navigation';
import a5 from '../../images/people/a5.jpg';
import a6 from '../../images/people/a6.jpg';
import s from './Header.module.scss'; // eslint-disable-line css-modules/no-unused-class
class Header extends React.Component {
static propTypes = {
sidebarOpened: PropTypes.bool.isRequired,
sidebarStatic: PropTypes.bool.isRequired,
chatToggle: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
location: PropTypes.shape({
pathname: PropTypes.string,
}).isRequired,
};
constructor(props) {
super(props);
this.toggleMenu = this.toggleMenu.bind(this);
this.switchSidebar = this.switchSidebar.bind(this);
this.toggleNotifications = this.toggleNotifications.bind(this);
this.toggleSidebar = this.toggleSidebar.bind(this);
this.doLogout = this.doLogout.bind(this);
this.state = {
menuOpen: false,
notificationsOpen: false,
notificationsTabSelected: 1,
};
}
componentDidMount() {
if (window.innerWidth > 576) {
setTimeout(() => {
const $chatNotification = $('#chat-notification');
$chatNotification.removeClass('hide').addClass('animated fadeIn')
.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', () => {
$chatNotification.removeClass('animated fadeIn');
setTimeout(() => {
$chatNotification.addClass('animated fadeOut')
.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd' +
' oanimationend animationend', () => {
$chatNotification.addClass('hide');
});
}, 6000);
});
$chatNotification.siblings('#toggle-chat')
.append('<i class="chat-notification-sing animated bounceIn"></i>');
}, 4000);
}
$('#search-input').on('blur focus', (e) => {
$('#search-input').parents('.input-group')[e.type === 'focus' ? 'addClass' : 'removeClass']('focus');
});
}
toggleNotifications() {
this.setState({
notificationsOpen: !this.state.notificationsOpen,
});
}
doLogout() {
this.props.dispatch(logoutUser());
}
// collapse/uncolappse
switchSidebar() {
if (this.props.sidebarOpened) {
this.props.dispatch(closeSidebar());
this.props.dispatch(changeActiveSidebarItem(null));
} else {
const paths = this.props.location.pathname.split('/');
paths.pop();
this.props.dispatch(openSidebar());
this.props.dispatch(changeActiveSidebarItem(paths.join('/')));
}
}
// static/non-static
toggleSidebar() {
this.props.dispatch(toggleSidebar());
if (this.props.sidebarStatic) {
localStorage.setItem('staticSidebar', 'false');
this.props.dispatch(changeActiveSidebarItem(null));
} else {
localStorage.setItem('staticSidebar', 'true');
const paths = this.props.location.pathname.split('/');
paths.pop();
this.props.dispatch(changeActiveSidebarItem(paths.join('/')));
}
}
toggleMenu() {
this.setState({
menuOpen: !this.state.menuOpen,
});
}
render() {
const user = JSON.parse(localStorage.getItem('user') || {});
const firstUserLetter = (user.name|| user.email || "P")[0].toUpperCase();
return (
<Navbar className={`${s.root} d-print-none`}>
<Nav>
<NavItem>
<NavLink className="d-md-down-none ml-5" id="toggleSidebar" onClick={this.toggleSidebar}>
<i className="la la-bars" />
</NavLink>
<UncontrolledTooltip placement="bottom" target="toggleSidebar">
Turn on/off<br />sidebar<br />collapsing
</UncontrolledTooltip>
<NavLink className="fs-lg d-lg-none" onClick={this.switchSidebar}>
<span className="rounded rounded-lg bg-gray text-white d-md-none"><i className="la la-bars" /></span>
<i className="la la-bars ml-3 d-sm-down-none" />
</NavLink>
</NavItem>
<NavItem className="d-sm-down-none">
<NavLink className="px-2">
<i className="la la-refresh" />
</NavLink>
</NavItem>
<NavItem className="d-sm-down-none">
<NavLink className="px-2">
<i className="la la-times" />
</NavLink>
</NavItem>
</Nav>
<Form className="d-sm-down-none ml-5" inline>
<FormGroup>
<InputGroup className="input-group-no-border">
<InputGroupAddon addonType="prepend">
<i className="la la-search" />
</InputGroupAddon>
<Input id="search-input" placeholder="Search Dashboard" />
</InputGroup>
</FormGroup>
</Form>
<NavLink className={`${s.navbarBrand} d-md-none`}>
<i className="fa fa-circle text-gray mr-n-sm" />
<i className="fa fa-circle text-warning" />
&nbsp;
sing
&nbsp;
<i className="fa fa-circle text-warning mr-n-sm" />
<i className="fa fa-circle text-gray" />
</NavLink>
<Nav className="ml-auto">
<Dropdown nav isOpen={this.state.notificationsOpen} toggle={this.toggleNotifications} id="basic-nav-dropdown" className={`${s.notificationsMenu} d-sm-down-none`}>
<DropdownToggle nav caret>
<span className={`${s.avatar} rounded-circle thumb-sm float-left mr-2`}>
{user.avatar || user.email === "admin@flatlogic.com" ? (
<img src={user.avatar || a5} alt="..."/>
) : (
<span>{firstUserLetter}</span>
)}
</span>
<span className="small">{user.name || user.email || "Philip smith"}</span>
<span className="ml-1 circle bg-warning text-white fw-bold">13</span>
</DropdownToggle>
<DropdownMenu right className={`${s.notificationsWrapper} py-0 animated animated-fast fadeInUp`}>
<Notifications />
</DropdownMenu>
</Dropdown>
<Dropdown nav isOpen={this.state.menuOpen} toggle={this.toggleMenu} className="d-sm-down-none">
<DropdownToggle nav>
<i className="la la-cog" />
</DropdownToggle>
<DropdownMenu right className="super-colors">
<DropdownItem><i className="la la-user" /> My Account</DropdownItem>
<DropdownItem divider />
<DropdownItem href="/calendar">Calendar</DropdownItem>
<DropdownItem href="/inbox">Inbox &nbsp;&nbsp;<Badge color="danger" pill className="animated bounceIn">9</Badge></DropdownItem>
<DropdownItem divider />
<DropdownItem onClick={this.doLogout}><i className="la la-sign-out" /> Log Out</DropdownItem>
</DropdownMenu>
</Dropdown>
<NavItem>
<NavLink className="d-sm-down-none mr-5" id="toggle-chat" onClick={this.props.chatToggle}>
<i className="la la-globe" />
</NavLink>
<div id="chat-notification" className={`${s.chatNotification} hide `}>
<div className={s.chatNotificationInner}>
<h6 className={`${s.title} d-flex`}>
<span className="thumb-xs">
<img src={a6} alt="" className="rounded-circle mr-xs float-left" />
</span>
Jess Smith
</h6>
<p className={s.text}>Hi there! <br /> This is a completely new version of Sing App <br /> built with <strong className="text-primary">React JS</strong> </p>
</div>
</div>
</NavItem>
<NavItem className="fs-lg d-md-none">
<NavLink href="#" onClick={this.props.chatToggle}>
<span className="rounded rounded-lg bg-gray text-white"><i className="la la-globe" /></span>
</NavLink>
</NavItem>
</Nav>
</Navbar>
);
}
}
function mapStateToProps(store) {
return {
sidebarOpened: store.navigation.sidebarOpened,
sidebarStatic: store.navigation.sidebarStatic,
};
}
export default withRouter(connect(mapStateToProps)(Header));
@import '../../styles/app';
.root {
z-index: 100;
background: var(--navbar-bg);
box-shadow: var(--navbar-shadow);
@include media-breakpoint-down(sm) {
padding: 7px 0;
}
:global {
.input-group {
overflow: hidden;
}
.input-group-prepend {
background-color: #fff;
transition: background-color ease-in-out 0.15s;
border-top-left-radius: 0.3rem;
border-bottom-left-radius: 0.3rem;
display: flex;
justify-content: center;
align-items: center;
width: 35px;
}
.focus .input-group-prepend {
background: #f8f9fa;
}
}
}
.logo {
font-size: 16px;
}
.navbarForm {
padding: 6px 0 6px 1rem;
margin-left: 10px;
display: inline-block;
top: 2px;
width: auto;
.inputAddon {
position: relative;
display: inline;
border: none;
background-color: #fff;
transition: background-color ease-in-out 0.15s;
}
input {
border: none;
padding: 0.6rem 0.85rem 0.6rem 0;
display: inline !important;
width: 250px !important;
top: 2px;
}
}
.chatNotification {
position: absolute;
right: 35px;
top: 50px;
z-index: 20;
margin-top: 3px;
padding: 5px 0;
cursor: pointer;
&::before {
content: ' ';
position: absolute;
top: 0;
right: 18px;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid $gray-800;
}
.chatNotificationInner {
min-width: 120px;
padding: 8px;
font-size: 12px;
border-radius: 0.25rem;
text-decoration: none;
background-color: $gray-800;
color: #fff;
}
.text {
margin-top: 5px;
margin-bottom: 0;
color: $gray-600;
}
.title {
margin: 0;
font-weight: 600;
line-height: 28px;
font-size: 0.875rem;
span {
margin-right: 7px;
}
}
}
.navbarBrand {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
font-weight: 700;
font-size: 1.25rem;
pointer-events: none;
i {
font-size: 10px;
}
}
.notificationsMenu {
:global .dropdown-menu {
left: auto !important;
right: 0 !important;
top: $navbar-height !important;
}
}
.notificationsWrapper {
width: min-content;
}
.avatar {
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
height: 40px;
width: 40px;
background: $warning;
font-weight: 600;
font-size: 18px;
}
import React, { Component } from 'react';
import cx from 'classnames';
import { Button } from 'reactstrap';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { DashboardThemes } from '../../reducers/layout';
import { changeTheme } from '../../actions/layout';
import Widget from '../Widget';
import s from './Helper.module.scss'; // eslint-disable-line
import themeDark from '../../images/theme-dark.png';
import themeLight from '../../images/theme-light.png';
class Helper extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
dashboardTheme: PropTypes.string
};
static defaultProps = {
dashboardTheme: DashboardThemes.DARK
};
state = { isOpened: false };
toggle = () => {
this.setState(prevState => ({
isOpened: !prevState.isOpened,
}));
};
changeTheme = (state) => {
this.props.dispatch(changeTheme(state));
};
render() {
const { isOpened } = this.state;
return (
<div className={cx(s.themeHelper, { [s.themeHelperOpened]: isOpened })}>
<Widget
className={s.themeHelperContent}
bodyClass="mt-3"
title={
<header className={cx(s.themeHelperHeader, 'd-flex p-0')}>
<Button color="warning" className={s.themeHelperBtn} onClick={this.toggle}>
<div className={cx(s.themeHelperSpinner, 'text-white')}>
<i className="la la-cog" />
<i className="la la-cog" />
</div>
</Button>
<h6>Theme</h6>
</header>
}
>
<div className={s.themeSwitcher}>
<div className={cx(s.theme, "mb-3")}>
<input checked={this.props.dashboardTheme === DashboardThemes.LIGHT} onClick={() => this.changeTheme(DashboardThemes.LIGHT)} type="radio" id="css-light" value="option2" name="theme-variant" aria-label="Sing Light" readOnly/>
<label htmlFor="css-light">
<img className={s.themeImage} src={themeLight} alt="light theme"/>
</label>
</div>
<div className={s.theme}>
<input checked={this.props.dashboardTheme === DashboardThemes.DARK} onClick={() => this.changeTheme(DashboardThemes.DARK)} type="radio" id="css-dark" value="option1" name="theme-variant" aria-label="Single Dark" readOnly/>
<label htmlFor="css-dark">
<img className={s.themeImage} src={themeDark} alt="dark theme"/>
</label>
</div>
</div>
<div className="mt-4">
<Button
href="https://flatlogic.com/admin-dashboards/sing-app-react"
target="_blank"
className="btn-rounded-f btn-block fs-mini"
color="warning"
>
<span className="text-white">Purchase</span>
</Button>
<Button
href="http://demo.flatlogic.com/sing-app/documentation/"
target="_blank"
className="btn-rounded-f btn-block fs-mini text-white"
>
Documentation
</Button>
</div>
<div className="d-flex justify-content-between mt-lg">
<Button
href="https://flatlogic.com/contact"
target="_blank"
className="btn-outline-default btn-rounded-f fs-mini text-muted px-2"
>
<i className="glyphicon glyphicon-headphones mr-xs" />
Support
</Button>
<Button
href="https://github.com/flatlogic/sing-app"
target="_blank"
className="btn-outline-default btn-rounded-f fs-mini text-muted px-2"
>
<i className="fa fa-github mr-xs" />
Github
</Button>
</div>
<div className="mt-lg d-flex flex-column align-items-center theme-helper__sharing">
<span className="fs-sm">
Thank you for sharing!
</span>
<div className="d-flex justify-content-center text-light mt-2">
<a
target="_blank"
rel="noopener noreferrer"
href="https://twitter.com/intent/tweet?text=Amazing%20dashboard%20built%20with%20NodeJS,%20React%20and%20Bootstrap!&url=https://github.com/flatlogic/react-dashboard&via=flatlogic"
>
<i className="fa fa-twitter pr-1" />
</a>
<a
href="https://www.facebook.com/search/top/?q=flatlogic%20llc"
target="_blank"
rel="noopener noreferrer"
>
<i className="fa fa-facebook pl-1" />
</a>
</div>
</div>
</Widget>
</div>
);
}
}
function mapStateToProps(store) {
return {
dashboardTheme: store.layout.dashboardTheme,
};
}
export default connect(mapStateToProps)(Helper);
@import '../../styles/app';
.themeHelper {
width: $sidebar-width-open;
position: fixed;
right: -$sidebar-width-open;
top: $navbar-height * 1.5;
z-index: 100;
@include transition(right $sidebar-transition-time ease-in-out);
& :global {
.abc-radio-secondary input[type="radio"]:not(:checked)+label::before {
background-color: #798892;
}
.abc-radio-warning input[type="radio"]:not(:checked)+label::before {
background-color: theme-color('warning');
}
}
.themeSwitcher {
display: flex;
flex-direction: column;
align-items: center;
.theme {
position: relative;
&,
& > label {
width: 100%;
height: max-content;
}
& > input {
position: absolute;
width: 0;
height: 0;
padding: 0;
margin: 0;
pointer-events: none;
opacity: 0;
}
& > label {
margin: 0;
border: 1px solid $input-border-color;
padding: 3px;
border-radius: $border-radius;
transition: background-color .2s ease-in-out;
cursor: pointer;
display: block;
&:hover {
background-color: $gray-200;
}
}
& > input:checked + label {
background-color: $gray-300;
}
.themeImage {
width: 100%;
}
}
}
&.themeHelperOpened {
right: 0;
}
.themeHelperBtn {
position: absolute;
width: $sidebar-width-open / 4;
transform: translateX(-76px);
margin-top: -($widget-padding-vertical);
cursor: pointer;
z-index: 200;
border-radius: 50% 0 0 50%;
padding: $spacer * 0.8 $spacer / 2 $spacer * 0.8 $spacer;
&,
&:not(.active) {
box-shadow: $widget-shadow-designated !important;
}
i {
animation-duration: 6500ms;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
i:first-of-type {
animation-name: spin;
margin-right: -$spacer * 1.15;
vertical-align: text-bottom;
}
i:last-of-type {
animation-name: spin-reverse;
vertical-align: $font-size-sm;
}
}
.themeHelperSpinner {
font-size: $font-size-lg * 1.4;
line-height: initial;
}
.themeHelperHeader {
padding-top: 0;
h6 {
margin: auto;
}
}
.themeHelperContent {
box-shadow: $widget-shadow-designated;
border-radius: 0;
}
.themeHelperSharing {
font-size: $font-size-lg;
cursor: pointer;
}
:global .glyphicon {
vertical-align: top;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(360deg);
}
}
@keyframes spin-reverse {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(-360deg);
}
}
}
import React from 'react';
import PropTypes from 'prop-types';
import Formsy from 'formsy-react';
Formsy.addValidationRule('isRange', (values, value, array) => (value >= array[0] && value <= array[1]));
class InputValidation extends React.Component {
/* eslint-disable */
static propTypes = {
trigger: PropTypes.string,
type: PropTypes.string,
className: PropTypes.string,
name: PropTypes.string,
id: PropTypes.string,
placeholder: PropTypes.string,
setValue: PropTypes.func,
isFormSubmitted: PropTypes.func,
getErrorMessage: PropTypes.func,
showRequired: PropTypes.func,
};
/* eslint-enable */
static defaultProps = {
trigger: null,
type: 'text',
className: '',
name: '',
id: '',
placeholder: '',
};
constructor() {
super();
this.changeValue = this.changeValue.bind(this);
}
changeValue(event) {
this.props.setValue(event.currentTarget.value);
}
render() {
const errorMessageObj = (this.props.isFormSubmitted() || this.props.trigger) ? this.props.getErrorMessage() : null;
const required = (this.props.isFormSubmitted() && this.props.showRequired()) ?
<span className={'help-block text-danger'}>This value is required.</span> : null;
const errorMsg = [];
if (errorMessageObj) {
Object.keys(errorMessageObj).forEach((type) => {
errorMsg.push(errorMessageObj[type]);
});
}
const errorList = errorMsg.map((msg, index) =>
<span key={`msg-err-${index.toString()}`} className={'help-block text-danger'}>{msg}</span>,
);
return (
<div className={this.props.className}>
<input
type={this.props.type}
name={this.props.name}
id={this.props.id}
className={'form-control'}
onBlur={this.changeValue}
placeholder={this.props.placeholder}
/>
{required}
{errorList}
</div>
);
}
}
export default Formsy.HOC(InputValidation);
This diff is collapsed. Click to expand it.
/* eslint-env mocha */
/* eslint-disable padded-blocks, no-unused-expressions */
import React from 'react';
import { expect } from 'chai';
import { render } from 'enzyme';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import App from '../App';
import Layout from './Layout';
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
const initialState = {};
describe('Layout', () => {
it('renders children correctly', () => {
const store = mockStore(initialState);
const wrapper = render(
<App context={{ insertCss: () => {}, store }}>
<Layout>
<div className="child" />
</Layout>
</App>,
);
expect(wrapper.find('div.child').length).to.eq(1);
});
});
import React from 'react';
import {
ButtonGroup,
Button,
} from 'reactstrap';
import classnames from 'classnames';
import NotificationsDemo from './notifications-demo/Notifications';
import NewNotificationsDemo from './notifications-demo/NewNotifications';
import MessagesDemo from './notifications-demo/Messages';
import ProgressDemo from './notifications-demo/Progress';
import s from './Notifications.module.scss';
class Notifications extends React.Component {
constructor(props) {
super(props);
this.state = {
notificationsTabSelected: 1,
newNotifications: null,
isLoad: false,
};
}
changeNotificationsTab(tab) {
this.setState({
notificationsTabSelected: tab,
newNotifications: null,
});
}
loadNotifications() {
this.setState({
isLoad: true,
});
setTimeout(() => {
this.setState({
newNotifications: (<NewNotificationsDemo />),
isLoad: false,
});
}, 1500);
}
render() {
let notificationsTab;
switch (this.state.notificationsTabSelected) {
case 1:
notificationsTab = (<NotificationsDemo />);
break;
case 2:
notificationsTab = (<MessagesDemo />);
break;
case 3:
notificationsTab = (<ProgressDemo />);
break;
default:
notificationsTab = (<NotificationsDemo />);
break;
}
return (
<section className={`${s.notifications} card navbar-notifications`}>
<header className={[s.cardHeader, 'card-header'].join(' ')}>
<div className="text-center mb-sm">
<strong>You have 13 notifications</strong>
</div>
<ButtonGroup id="notification-buttons">
<Button color="secondary" onClick={() => this.changeNotificationsTab(1)} active={this.state.notificationsTabSelected === 1}>Notifications</Button>
<Button color="secondary" onClick={() => this.changeNotificationsTab(2)} active={this.state.notificationsTabSelected === 2}>Messages</Button>
<Button color="secondary" onClick={() => this.changeNotificationsTab(3)} active={this.state.notificationsTabSelected === 3}>Progress</Button>
</ButtonGroup>
</header>
{this.state.newNotifications || notificationsTab}
<footer className={[s.cardFooter, 'text-sm', 'card-footer'].join(' ')}>
<Button
color="link"
className={classnames({ disabled: this.state.isLoad }, s.btnNotificationsReload, 'btn-xs', 'float-right', 'py-0')}
onClick={() => this.loadNotifications()}
id="load-notifications-btn"
>
{this.state.isLoad ? <span><i className="la la-refresh la-spin" /> Loading...</span> : <i className="la la-refresh" />}
</Button>
<span className="fs-mini">Synced at: 21 Apr 2014 18:36</span>
</footer>
</section>
);
}
}
export default Notifications;
@import '../../styles/app';
.notifications {
@include media-breakpoint-up(md) {
width: 333px;
}
height: 100%;
border: none;
}
.cardHeader {
border-radius: 0;
}
.cardFooter {
padding-top: 14px;
padding-bottom: 14px;
}
.btnNotificationsReload {
color: $navbar-link-color;
outline: none;
i::before {
top: 2px;
}
}
@import '../../../styles/app';
.listGroup {
display: block;
height: 320px;
overflow-y: scroll;
.listGroupItem:first-child {
border: none;
}
}
.listGroupItem {
transition: background-color 0.15s ease-in-out;
text-decoration: none;
color: $gray-700;
border-left: none;
border-right: none;
display: block;
:global .progress {
transition: background 0.15s ease-in-out;
&:hover {
background: $black;
}
}
&:hover {
background-color: $list-group-hover-bg;
:global .progress {
background: $white !important;
}
}
&:first-child {
border-top: none;
border-top-right-radius: 0;
border-top-left-radius: 0;
}
&:last-child {
border-bottom: none;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
}
.notificationIcon {
margin-right: 1rem;
float: left;
@include clearfix;
}
import React from 'react';
import {
ListGroup,
ListGroupItem,
} from 'reactstrap';
import a1 from '../../../images/people/a1.jpg';
import a2 from '../../../images/people/a2.jpg';
import a4 from '../../../images/people/a4.jpg';
import a6 from '../../../images/people/a6.jpg';
import avatar from '../../../images/avatar.png';
import s from './ListGroup.module.scss'; // eslint-disable-line
class MessagesDemo extends React.Component {
render() {
return (
<ListGroup className={[s.listGroup, 'thin-scroll'].join(' ')}>
<ListGroupItem className={[s.listGroupItem, 'bg-warning-light'].join(' ')}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a2} alt="..." />
<i className="status status-bottom bg-success" />
</span>
<time className="text-link help float-right">10 sec ago</time>
<h6 className="m-0 fw-bold mb-1">Chris Gray</h6>
<p className="deemphasize text-ellipsis m-0">Hey! What&apos;s up? So many times since we</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={avatar} alt="..." />
<i className="status status-bottom bg-success" />
</span>
<time className="text-link help float-right">2 min ago</time>
<h6 className="m-0 mb-1">Jamey Brownlow</h6>
<p className="deemphasize text-ellipsis m-0">Good news coming tonight. Seems they agreed to proceed</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a1} alt="..." />
<i className="status status-bottom bg-warning" />
</span>
<time className="text-link help float-right">9 min ago</time>
<h6 className="m-0 mb-1">Livia Walsh</h6>
<p className="deemphasize text-ellipsis m-0">Check out my latest email plz!</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={avatar} alt="..." />
<i className="status status-bottom bg-danger" />
</span>
<time className="text-link help float-right">12:56 AM</time>
<h6 className="m-0 mb-1">Jaron Fitzroy</h6>
<p className="deemphasize text-ellipsis m-0">What about summer break?</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a4} alt="..." />
<i className="status status-bottom bg-gray-light" />
</span>
<time className="text-link help float-right">Yesterday</time>
<h6 className="m-0 mb-1">Mike Lewis</h6>
<p className="deemphasize text-ellipsis m-0">Just ain&apos;t sure about the weekend now. 90% I&apos;ll make it.</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a6} alt="..." />
<i className="status status-bottom bg-success" />
</span>
<time className="text-link help float-right">Apr 23</time>
<h6 className="m-0 mb-1">Freda Edison</h6>
<p className="deemphasize text-ellipsis m-0">Hey what&apos;s up? Me and Monica going for a lunch somewhere. Wanna join?</p>
</ListGroupItem>
</ListGroup>
);
}
}
export default MessagesDemo;
import React from 'react';
import {
ListGroup,
ListGroupItem,
Button,
} from 'reactstrap';
import s from './ListGroup.module.scss';
import a3 from '../../../images/people/a3.jpg';
import a5 from '../../../images/people/a5.jpg';
import a6 from '../../../images/people/a6.jpg';
class NewNotificationsDemo extends React.Component {
render() {
return (
<ListGroup className={[s.listGroup, 'thin-scroll'].join(' ')}>
<ListGroupItem className={`${s.listGroupItem} bg-attention`}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<i className="fa fa-check text-success fa-lg" />
</span>
<p className="m-0 overflow-hidden">
2 issues require your approval.
{/* eslint-disable */}
&nbsp;<a href="#">The Search Project</a> completed on time!
{/* eslint-enable */}
<time className="help-block m-0">
just now
</time>
</p>
</ListGroupItem>
<ListGroupItem className={`${s.listGroupItem} bg-attention`}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a6} alt="..." />
</span>
<p className="m-0 overflow-hidden">
<button className="btn-link">Jeniffer Willington</button>has just endorsed you with 50 points!
<time className="help-block m-0">
30 sec ago
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a3} alt="..." />
</span>
<p className="m-0 overflow-hidden">
1 new user just signed up! Check out
{/* eslint-disable */}
&nbsp;<a href="#">Monica Smith</a>'s account.
{/* eslint-enable */}
<time className="help-block m-0">
2 mins ago
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<i className="glyphicon glyphicon-upload fa-lg" />
</span>
<p className="text-ellipsis m-0">
2.1.0-pre-alpha just released.
<time className="help-block m-0">
5h ago
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<i className="fa fa-bolt fa-lg" />
</span>
<p className="text-ellipsis m-0 overflow-hidden">
Server load limited.
<time className="help-block m-0">
7h ago
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a5} alt="..." />
</span>
<p className="m-0 overflow-hidden">
{/* eslint-disable */}
User <a href="#">Jeff</a> registered
{/* eslint-enable */}
&nbsp;&nbsp;
<Button size="xs" color="success" className="mr-1">Allow</Button>
<Button size="xs" color="danger">Deny</Button>
<time className="help-block m-0">
12:18 AM
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<i className="fa fa-shield fa-lg" />
</span>
<p className="m-0 overflow-hidden">
{/* eslint-disable */}
Instructions for changing your Envato Account password. Please
check your account <a href="#">security page</a>.
{/* eslint-enable */}
<time className="help-block m-0">
12:18 AM
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<span className="rounded bg-primary rounded-lg">
<i className="fa fa-facebook text-white" />
</span>
</span>
<p className="text-ellipsis m-0">
New <strong>76</strong> facebook likes received.
<time className="help-block m-0">
15 Apr 2014
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<span className="circle circle-lg bg-gray-dark">
<i className="fa fa-circle-o text-white" />
</span>
</span>
<p className="text-ellipsis m-0">
Dark matter detected.
<time className="help-block m-0">
15 Apr 2014
</time>
</p>
</ListGroupItem>
</ListGroup>
);
}
}
export default NewNotificationsDemo;
import React from 'react';
import {
ListGroup,
ListGroupItem,
Button,
} from 'reactstrap';
import s from './ListGroup.module.scss';
import a3 from '../../../images/people/a3.jpg';
import a5 from '../../../images/people/a5.jpg';
class NotificationsDemo extends React.Component {
render() {
return (
<ListGroup className={[s.listGroup, 'thin-scroll'].join(' ')}>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a3} alt="..." />
</span>
<p className="m-0 overflow-hidden">
1 new user just signed up! Check out
{/* eslint-disable */}
&nbsp;<a href="#">Monica Smith</a>'s account.
{/* eslint-enable */}
<time className="help-block m-0">
2 mins ago
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<i className="glyphicon glyphicon-upload fa-lg" />
</span>
<p className="text-ellipsis m-0">
2.1.0-pre-alpha just released.
<time className="help-block m-0">
5h ago
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<i className="fa fa-bolt fa-lg" />
</span>
<p className="text-ellipsis m-0 overflow-hidden">
Server load limited.
<time className="help-block m-0">
7h ago
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<img className="rounded-circle" src={a5} alt="..." />
</span>
<p className="m-0 overflow-hidden">
{/* eslint-disable */}
User <a href="#">Jeff</a> registered
{/* eslint-enable */}
&nbsp;&nbsp;
<Button size="xs" color="success" className="mr-1">Allow</Button>
<Button size="xs" color="danger">Deny</Button>
<time className="help-block m-0">
12:18 AM
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<i className="fa fa-shield fa-lg" />
</span>
<p className="m-0 overflow-hidden">
{/* eslint-disable */}
Instructions for changing your Envato Account password. Please
check your account <a href="#">security page</a>.
{/* eslint-enable */}
<time className="help-block m-0">
12:18 AM
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<span className="rounded bg-primary rounded-lg">
<i className="fa fa-facebook text-white" />
</span>
</span>
<p className="text-ellipsis m-0">
New <strong>76</strong> facebook likes received.
<time className="help-block m-0">
15 Apr 2014
</time>
</p>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className={[s.notificationIcon, 'thumb-sm'].join(' ')}>
<span className="circle circle-lg bg-gray-dark">
<i className="fa fa-circle-o text-white" />
</span>
</span>
<p className="text-ellipsis m-0">
Dark matter detected.
<time className="help-block m-0">
15 Apr 2014
</time>
</p>
</ListGroupItem>
</ListGroup>
);
}
}
export default NotificationsDemo;
import React from 'react';
import {
ListGroup,
ListGroupItem,
Progress,
UncontrolledTooltip,
} from 'reactstrap';
import s from './ListGroup.module.scss'; // eslint-disable-line
class ProgressDemo extends React.Component {
render() {
return (
<ListGroup className={[s.listGroup, 'thin-scroll'].join(' ')}>
<ListGroupItem className={s.listGroupItem}>
<span className="text-muted float-right">60%</span>
<h6 className="m-0 mb-1 text-gray">
<strong>Urgent:</strong>
&nbsp;Rails 4.1.0 upgrade
</h6>
<Progress className={['m-0'].join(' ')} color="primary" value="60" />
<span className="help-block">3 notes added by James 2h ago...</span>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className="text-muted float-right">83%</span>
<h6 className="m-0 mb-1 text-gray">
<strong>Primary:</strong>
&nbsp;Sing Web App
</h6>
<Progress className={['progress-sm', 'm-0'].join(' ')} color="success" value="83" />
<span className="help-block">verifying stable probability status</span>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className="text-muted float-right">44%</span>
<h6 className="m-0 mb-1">
<span className="circle bg-gray-dark text-warning" id="TooltipQuestion">
<i className="fa fa-question" />
</span>
<UncontrolledTooltip placement="bottom" target="TooltipQuestion">
2 issues require your attention
</UncontrolledTooltip>
&nbsp;
Finish The Road to Hell Song
</h6>
<Progress className={['progress-sm', 'm-0'].join(' ')} color="gray-dark" value="44" />
<span className="help-block">last update: 2h ago</span>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className="text-muted float-right">86%</span>
<h6 className="m-0 mb-1 deemphasize text-gray">
Complete project planning
</h6>
<Progress className={['progress-xs', 'm-0'].join(' ')} color="danger" value="86" />
<span className="help-block">no, no way this is not working...</span>
</ListGroupItem>
<ListGroupItem className={s.listGroupItem}>
<span className="text-muted float-right">100%</span>
<h6 className="m-0 mb-1 deemphasize text-gray">
<strong>Completed:</strong>
&nbsp;Instruct newbies on coding standards
</h6>
<Progress className={['progress-xs', 'm-0'].join(' ')} color="primary" value="100" />
<span className="help-block">last update: April 22, 2014 2:36 pm</span>
</ListGroupItem>
</ListGroup>
);
}
}
export default ProgressDemo;
......@@ -9,7 +9,7 @@
a {
display: block;
color: var(--sidebar-color);
color: #a6b2c1;
text-decoration: none;
cursor: pointer;
......
This diff is collapsed. Click to expand it.
import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
const Skycons = require('skycons')(window || {});
class Skycon extends React.Component {
static propTypes = {
color: PropTypes.string.isRequired,
autoPlay: PropTypes.bool,
icon: PropTypes.oneOf([ // eslint-disable-line
'CLEAR_DAY',
'CLEAR_NIGHT',
'PARTLY_CLOUDY_DAY',
'PARTLY_CLOUDY_NIGHT',
'CLOUDY',
'RAIN',
'SLEET',
'SNOW',
'WIND',
'FOG',
]),
width: PropTypes.string.isRequired,
height: PropTypes.string.isRequired,
};
static defaultProps = {
color: null,
autoPlay: true,
width: '100%',
height: '100%',
};
constructor(props) {
super(props);
this.state = {
skycons: new Skycons({ color: this.props.color }),
};
}
componentDidMount() {
const { skycons } = this.state;
skycons.add(ReactDOM.findDOMNode(this), Skycons[this.props.icon]); // eslint-disable-line
if (this.props.autoPlay) {
skycons.play();
}
}
componentWillReceiveProps(nextProps) {
this.state.skycons.set(ReactDOM.findDOMNode(this), Skycons[nextProps.icon]); // eslint-disable-line
}
play() {
this.state.skycons.play();
}
pause() {
this.state.skycons.pause();
}
render() {
const {
...restPops
} = this.props;
return (
<canvas width={this.props.width} height={this.props.height} {...restPops} />
);
}
}
export default Skycon;
import React from 'react';
import $ from 'jquery';
import PropTypes from 'prop-types';
/* eslint-disable */
import 'imports-loader?jQuery=jquery,this=>window!jquery-sparkline';
/* eslint-enable */
class Sparklines extends React.Component {
static propTypes = {
data: PropTypes.arrayOf(
PropTypes.arrayOf(PropTypes.number),
),
options: PropTypes.oneOfType([
PropTypes.arrayOf(
PropTypes.shape({
type: PropTypes.string.isRequired,
}),
),
PropTypes.shape({
type: PropTypes.string.isRequired,
}),
]),
};
static defaultProps = {
data: [],
options: {},
};
componentDidMount() {
this.initSparkline();
}
initSparkline() {
const $el = $(this.sparklineRef);
const model = $.type(this.data) === 'string' ?
this.props.data.replace(/(^,)|(,$)/g, '')
: this.props.data;
const options = this.props.options;
if ($.type(model) === 'array' && $.type(options) === 'array') {
options.forEach((singleOptions, i) => {
if (i === 0) {
$el.sparkline(model[i], singleOptions);
} else { // set composite for next calls
$el.sparkline(model[i], $.extend({ composite: true }, singleOptions));
}
});
} else {
const data = $.type(model) === 'array' ? model : model.split(',');
$el.sparkline(data, options);
}
}
render() {
return (
<div
className="sparkline" ref={(r) => {
this.sparklineRef = r;
}}
/>
);
}
}
export default Sparklines;
const hostApi = process.env.NODE_ENV === "development" ? "http://localhost" : "https://flatlogic-node-backend.herokuapp.com";
const portApi = process.env.NODE_ENV === "development" ? 8080 : "";
const hostApi = process.env.NODE_ENV === "development" ? "http://localhost" : "http://localhost";
const portApi = process.env.NODE_ENV === "development" ? 8080 : 4000;
const baseURLApi = `${hostApi}${portApi ? `:${portApi}` : ``}`;
export default {
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class Bundle extends Component {
static propTypes = {
load: PropTypes.func.isRequired,
children: PropTypes.func.isRequired,
};
static generateBundle = loadModule => () => (
/* eslint-disable */
<Bundle load={loadModule}>
{Mod => Mod ? <Mod /> : <div style={{ textAlign: 'center', paddingTop: '35vh' }}>Loading</div>}
</Bundle>
/* eslint-enable */
);
state = {
// short for "module" but that's a keyword in js, so "mod"
mod: null,
};
componentWillMount() {
this.load(this.props);
}
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps);
}
}
load(props) {
this.setState({
mod: null,
});
props.load((mod) => {
this.setState({
// handle both es imports and cjs
mod: mod.default ? mod.default : mod,
});
});
}
render() {
return this.props.children(this.state.mod);
}
}
export default Bundle;
const config = {
name: 'sing',
title: 'Sing Dashboard App built with React JS by Flatlogic',
name: 'Video Emergency Detection',
title: 'Video Emergency Detection',
version: '3.8.0',
settings: {
screens: {
......
import React, { Component } from 'react';
import hoistStatics from 'hoist-non-react-statics';
import { updateMeta } from '../DOMUtils';
import { defaultMeta } from '../config';
function withMeta(ComposedComponent) {
class WithMeta extends Component {
componentWillMount() {
if (ComposedComponent.meta) {
Object.keys(ComposedComponent.meta).forEach((metaKey) => {
if (metaKey === 'title') {
document.title = `${ComposedComponent.meta[metaKey]} - ${defaultMeta[metaKey]}`;
return;
}
updateMeta(metaKey, ComposedComponent.meta[metaKey]);
});
}
}
componentWillUnmount() {
Object.keys(defaultMeta).forEach((metaKey) => {
if (metaKey === 'title') {
document.title = defaultMeta[metaKey];
return;
}
updateMeta(metaKey, defaultMeta[metaKey]);
});
}
render() {
return <ComposedComponent {...this.props} />;
}
}
WithMeta.ComposedComponent = ComposedComponent;
return hoistStatics(WithMeta, ComposedComponent);
}
export default withMeta;
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Link } from 'react-router-dom';
import { withRouter } from 'react-router';
import {
Navbar,
Nav,
NavItem,
NavLink,
} from 'reactstrap';
import { openSidebar, closeSidebar, changeActiveSidebarItem } from '../actions/navigation';
import s from '../components/Header/Header.module.scss'; // eslint-disable-line css-modules/no-unused-class
import sd from './styles.module.scss';
import twitterLogo from '../images/documentation/twitter-logo.svg';
import dribbleLogo from '../images/documentation/dribble-logo.svg';
import facebookLogo from '../images/documentation/facebook-logo.svg';
import instagramLogo from '../images/documentation/instagram-logo.svg';
import linkedinLogo from '../images/documentation/linkedin-logo.svg';
import githubLogo from '../images/documentation/github-logo.svg';
class Header extends React.Component {
static propTypes = {
sidebarOpened: PropTypes.bool.isRequired,
sidebarStatic: PropTypes.bool.isRequired,
chatToggle: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
location: PropTypes.shape({
pathname: PropTypes.string,
}).isRequired,
};
constructor(props) {
super(props);
this.toggleMenu = this.toggleMenu.bind(this);
this.switchSidebar = this.switchSidebar.bind(this);
this.state = {
menuOpen: false,
notificationsOpen: false,
notificationsTabSelected: 1,
};
}
// collapse/uncolappse
switchSidebar() {
if (this.props.sidebarOpened) {
this.props.dispatch(closeSidebar());
this.props.dispatch(changeActiveSidebarItem(null));
} else {
const paths = this.props.location.pathname.split('/');
paths.pop();
this.props.dispatch(openSidebar());
this.props.dispatch(changeActiveSidebarItem(paths.join('/')));
}
}
toggleMenu() {
this.setState({
menuOpen: !this.state.menuOpen,
});
}
render() {
return (
<Navbar className={classnames(s.root, sd.header, 'd-print-none')}>
<div className="container">
<div className="row w-100 d-flex align-items-center">
<Nav>
<NavItem>
<NavLink className="fs-lg d-lg-none d-md-none" onClick={this.switchSidebar}>
<span className="rounded rounded-lg text-white d-md-none"><i className="la la-bars" /></span>
<i className="la la-bars ml-3 d-sm-down-none" />
</NavLink>
</NavItem>
<NavItem>
<NavLink className={classnames(s.logo, 'd-sm-down-none px-4')} href={'/documentation'}>
<span className={'fw-semi-bold'}>Sing App React</span> &nbsp; Documentation
</NavLink>
</NavItem>
</Nav>
<NavLink className={`${s.navbarBrand} d-md-none text-muted`}>
<i className="fa fa-circle text-gray mr-n-sm" />
<i className="fa fa-circle text-warning" />
&nbsp;
documentation
&nbsp;
<i className="fa fa-circle text-warning mr-n-sm" />
<i className="fa fa-circle text-muted" />
</NavLink>
<Nav className="ml-auto">
<NavItem className="d-flex alight-items-center d-md-down-none">
<NavLink href="https://twitter.com/flatlogic" className="mr-1">
<img src={twitterLogo} alt="twitter" />
</NavLink>
<NavLink href="https://dribbble.com/flatlogic" className="mr-1">
<img src={dribbleLogo} alt="dribble" />
</NavLink>
<NavLink href="https://dribbble.com/flatlogic" className="mr-1">
<img src={facebookLogo} alt="facebook" />
</NavLink>
<NavLink href="https://instagram.com/flatlogiccom/" className="mr-1">
<img src={instagramLogo} alt="instagram" />
</NavLink>
<NavLink href="https://www.linkedin.com/company/flatlogic/" className="mr-1">
<img src={linkedinLogo} alt="linkedin" />
</NavLink>
<NavLink href="https://github.com/flatlogic" className="mr-3">
<img src={githubLogo} alt="github" />
</NavLink>
</NavItem>
<NavItem className="d-flex align-items-center">
<NavItem className="d-md-down-none">
<Link to="/" className="btn btn-default">
Live Preview
</Link>
</NavItem>
<NavLink href="https://flatlogic.com/admin-dashboards/sing-app-react" target="_blank" className="mr-1">
<button className="btn btn-warning text-gray fw-semi-bold">
Buy Now
</button>
</NavLink>
</NavItem>
</Nav>
</div>
</div>
</Navbar>
);
}
}
function mapStateToProps(store) {
return {
sidebarOpened: store.navigation.sidebarOpened,
sidebarStatic: store.navigation.sidebarStatic,
};
}
export default withRouter(connect(mapStateToProps)(Header));
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Col } from 'reactstrap';
import classnames from 'classnames';
import { Switch, Route, withRouter } from 'react-router';
import Hammer from 'rc-hammerjs';
import Header from './DocumentationHeader';
import Sidebar from './DocumentationSidebar';
import { openSidebar, closeSidebar, changeActiveSidebarItem, toggleSidebar } from '../actions/navigation';
import s from '../components/Layout/Layout.module.scss';
import sd from './styles.module.scss';
import Overview from './pages/getting-started/Overview'
import Licences from './pages/getting-started/Licences';
import QuickStart from './pages/getting-started/QuickStart';
import Alerts from './pages/components/Alerts';
import Badge from './pages/components/Badge';
import Buttons from './pages/components/Buttons';
import Card from './pages/components/Card';
import Carousel from './pages/components/Carousel';
import Modal from './pages/components/Modal';
import Nav from './pages/components/Nav';
import Navbar from './pages/components/Navbar';
import Popovers from './pages/components/Popovers';
import Progress from './pages/components/Progress';
import Tabs from './pages/components/Tabs';
import Libs from './pages/Libs';
import Pages from './pages/Pages';
class Layout extends React.Component {
static propTypes = {
sidebarStatic: PropTypes.bool,
sidebarOpened: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
};
static defaultProps = {
sidebarStatic: false,
sidebarOpened: false,
};
constructor(props) {
super(props);
this.handleSwipe = this.handleSwipe.bind(this);
this.state = {
chatOpen: false,
width: window.innerWidth,
};
}
componentDidMount() {
const staticSidebar = JSON.parse(localStorage.getItem('staticSidebar'));
if (staticSidebar) {
this.props.dispatch(toggleSidebar());
} else if (this.props.sidebarOpened) {
setTimeout(() => {
this.props.dispatch(closeSidebar());
this.props.dispatch(changeActiveSidebarItem(null));
}, 2500);
}
window.addEventListener('resize', this.handleResize.bind(this));
}
handleResize() {
this.setState({
width: window.innerWidth,
})
if(window.innerWidth < 768 && this.props.sidebarOpened) {
this.props.dispatch(closeSidebar());
}
}
handleSwipe(e) {
if ('ontouchstart' in window) {
if (e.direction === 4 && !this.state.chatOpen) {
this.props.dispatch(openSidebar());
return;
}
if (e.direction === 2 && this.props.sidebarOpened) {
this.props.dispatch(closeSidebar());
return;
}
}
}
render() {
return (
<div
className={[
s.root,
sd.root,
this.state.width > 768 && s.sidebarStatic,
this.state.width < 768 && !this.props.sidebarOpened ? s.sidebarClose : '',
].join(' ')}
>
<Header />
<div>
<Hammer onSwipe={this.handleSwipe}>
<main className={classnames(s.content, sd.content)}>
<div className="container">
<div className="row">
<Sidebar width={this.state.width} />
<Col xl={10} md={9}>
<Switch>
<Route path="/documentation/getting-started/overview" exact component={Overview} />
<Route path="/documentation/getting-started/licences" exact component={Licences} />
<Route path="/documentation/getting-started/quick-start" exact component={QuickStart} />
<Route path="/documentation/components/alerts" exact component={Alerts} />
<Route path="/documentation/components/badge" exact component={Badge} />
<Route path="/documentation/components/buttons" exact component={Buttons} />
<Route path="/documentation/components/card" exact component={Card} />
<Route path="/documentation/components/carousel" exact component={Carousel} />
<Route path="/documentation/components/modal" exact component={Modal} />
<Route path="/documentation/components/nav" exact component={Nav} />
<Route path="/documentation/components/navbar" exact component={Navbar} />
<Route path="/documentation/components/popovers" exact component={Popovers} />
<Route path="/documentation/components/tabs-accordion" exact component={Tabs} />
<Route path="/documentation/components/progress" exact component={Progress} />
<Route path="/documentation/libs" exact component={Libs} />
<Route path="/documentation/pages" exact component={Pages} />
</Switch>
</Col>
</div>
</div>
</main>
</Hammer>
</div>
</div>
);
}
}
function mapStateToProps(store) {
return {
sidebarOpened: store.navigation.sidebarOpened,
sidebarStatic: store.navigation.sidebarStatic,
};
}
export default withRouter(connect(mapStateToProps)(Layout));
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { connect } from 'react-redux';
import { Col } from 'reactstrap';
import { withRouter } from 'react-router-dom';
import s from '../components/Sidebar/Sidebar.module.scss';
import sd from './styles.module.scss'
import { LinksGroup } from './components';
import { openSidebar, closeSidebar, changeActiveSidebarItem } from '../actions/navigation';
import isScreen from '../core/screenHelper';
class Sidebar extends React.Component {
static propTypes = {
sidebarStatic: PropTypes.bool,
sidebarOpened: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
activeItem: PropTypes.string,
location: PropTypes.shape({
pathname: PropTypes.string,
}).isRequired,
};
static defaultProps = {
sidebarStatic: false,
sidebarOpened: false,
activeItem: '',
};
constructor(props) {
super(props);
this.onMouseEnter = this.onMouseEnter.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
}
onMouseEnter() {
if (!this.props.sidebarStatic && (isScreen('lg') || isScreen('xl'))) {
const paths = this.props.location.pathname.split('/');
paths.pop();
this.props.dispatch(openSidebar());
this.props.dispatch(changeActiveSidebarItem(paths.join('/')));
}
}
onMouseLeave() {
if (!this.props.sidebarStatic && (isScreen('lg') || isScreen('xl'))) {
this.props.dispatch(closeSidebar());
this.props.dispatch(changeActiveSidebarItem(null));
}
}
render() {
return (
<Col xl={2} md={3}>
<nav
className={[s.root, sd.sidebar, this.props.width > 768 && s.staticSidebar].join(' ')}
>
<ul className={classnames(s.nav, sd.nav)}>
<LinksGroup
onActiveSidebarItemChange={activeItem => this.props.dispatch(changeActiveSidebarItem(activeItem))}
activeItem={this.props.activeItem}
header="Getting Started"
isHeader
link="/documentation/getting-started"
index="getting-started"
childrenLinks={[
{
header: 'Overview', link: '/documentation/getting-started/overview',
},
{
header: 'Licences', link: '/documentation/getting-started/licences',
},
{
header: 'Quick Start', link: '/documentation/getting-started/quick-start',
}
]}
/>
<LinksGroup
onActiveSidebarItemChange={activeItem => this.props.dispatch(changeActiveSidebarItem(activeItem))}
activeItem={this.props.activeItem}
header="Pages"
isHeader
link="/documentation/pages"
index="pages"
/>
<LinksGroup
onActiveSidebarItemChange={activeItem => this.props.dispatch(changeActiveSidebarItem(activeItem))}
activeItem={this.props.activeItem}
header="Components"
isHeader
link="/documentation/components"
index="components"
childrenLinks={[
{
header: 'Alerts', link: '/documentation/components/alerts',
},
{
header: 'Badge', link: '/documentation/components/badge',
},
{
header: 'Buttons', link: '/documentation/components/buttons',
},
{
header: 'Card', link: '/documentation/components/card',
},
{
header: 'Carousel', link: '/documentation/components/carousel',
},
{
header: 'Modal', link: '/documentation/components/modal',
},
{
header: 'Nav', link: '/documentation/components/nav',
},
{
header: 'Navbar', link: '/documentation/components/navbar',
},
{
header: 'Popovers & Tooltips', link: '/documentation/components/popovers',
},
{
header: 'Progress', link: '/documentation/components/progress',
},
{
header: 'Tabs & Accordion', link: '/documentation/components/tabs-accordion',
},
]}
/>
<LinksGroup
onActiveSidebarItemChange={activeItem => this.props.dispatch(changeActiveSidebarItem(activeItem))}
activeItem={this.props.activeItem}
header="Libs"
isHeader
link="/documentation/libs"
index="libs"
/>
{/*<LinksGroup*/}
{/*onActiveSidebarItemChange={activeItem => this.props.dispatch(changeActiveSidebarItem(activeItem))}*/}
{/*activeItem={this.props.activeItem}*/}
{/*header="FAQ"*/}
{/*isHeader*/}
{/*link="/documentation/faq"*/}
{/*index="faq"*/}
{/*childrenLinks={[*/}
{/*{*/}
{/*header: 'Analytics', link: '/app/main/analytics',*/}
{/*}*/}
{/*]}*/}
{/*/>*/}
</ul>
<a className={classnames('d-md-down-none', sd.company)} href="http://flatlogic.com/" target="_blank" rel="noopener noreferrer">
<img alt="company logo" src="https://cdn.dribbble.com/users/883507/avatars/small/7ca04141e335237d393ab41008adb46d.png?1509465697"/>
Proudly built and maintained by <br/> Flatlogic
</a>
</nav >
</Col>
);
}
}
function mapStateToProps(store) {
return {
sidebarOpened: store.navigation.sidebarOpened,
sidebarStatic: store.navigation.sidebarStatic,
alertsList: store.alerts.alertsList,
activeItem: store.navigation.activeItem,
};
}
export default withRouter(connect(mapStateToProps)(Sidebar));
import React from 'react';
import LinksGroupComponent from '../../components/Sidebar/LinksGroup/LinksGroup'
import s from './styles.module.scss';
export const LinksGroup = (props) => (
<div className={s.linksGroupWrapper}>
<LinksGroupComponent {...props} />
</div>
);
.linksGroupWrapper :global(.collapse ul),
.linksGroupWrapper :global(.collapsing ul),
.linksGroupWrapper :global(li > a):hover {
background: #FFFBF8 !important;
}
.linksGroupWrapper :global(li > a) {
color: #495057 !important;
}
This diff is collapsed. Click to expand it.
import React, {Component} from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
import ProductCard from '../../pages/products/components/ProductCard/ProductCard';
import products from '../../pages/products/mock'
import { Link } from 'react-router-dom';
import Widget from '../../components/Widget/Widget';
import Scrollspy from "./ScrollSpyComponent";
export default class Pages extends Component {
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem active>Pages</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<Widget id="Auth">
<h3>Auth</h3>
<p>Auth is a built-in module for an admin template dashboard. It contains all actions and handlers for any token authorization for your application.</p>
<p>All logic is in <code>src/actions/user.js</code> and <code>src/reducers/user.js</code>. We have already preconfigured <a href="https://github.com/flatlogic/nodejs-backend" rel="noopener noreferrer" target="_blank">Node.js backend</a>
<span className="small text-muted"> (Only in full stack version)</span> under the hood. <code>Creds</code> variable contains user email and password entered in the login form. It does request to our backend server and gets token and saves it in <code>localStorage</code>.</p>
<p><b>Important note.</b> Credentials validation must be on the server side.</p>
<p>Another important part of authentication is <code>PrivateRoute</code> component. That’s how it looks like.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>{'const PrivateRoute = ({ dispatch, component, ...rest }) => {\n' +
' if (!Login.isAuthenticated(localStorage.getItem(\'token\'))) {\n' +
' dispatch(logoutUser());\n' +
' return (<Redirect to=\'/login\'/>)\n' +
' } else {\n' +
' return (\n' +
' <Route {...rest} render={props => (React.createElement(component, props))}/>\n' +
' );\n' +
' }\n' +
'};'}</SyntaxHighlighter>
<p>We are getting <code>token</code> from local storage, that must be saved in local storage after successful loginUser function completion. Depends on the result of this action, <code>PrivateRoute</code> returns page (react component) or redirect to the login page. If you don’t need login functionality in your app, you can use <code>Route</code> instead of <code>PrivateRoute</code>.</p>
</Widget>
<Widget id="Inbox">
<h3>Inbox</h3>
<p>Inbox is a ready-to-use application with all needed features. It’s easy to understand and customize. The code is divided into components, so you can easily change the layout of your application.</p>
<ul>
<li>Messages filter & search</li>
<li>Compose</li>
<li>Read/unread, star/unstar, delete actionsy</li>
<li>Message attachments</li>
<li>Reply functionality</li>
</ul>
<Link className="btn btn-primary" to="/app/inbox">Demo</Link>
</Widget>
<Widget id="Dashboards">
<h3>Dashboards</h3>
<p>The main screen of any application built on the top of the admin dashboard template. That is more informative pages of all application. There are 2 types of dashboards: analytics and visits.</p>
<p>Analytics one. There you can find a lot of chart and statistics, calendar, todo manager, table with any data you need, notifications block.</p>
<p>Main chart made with D3.js library, most powerful charts library. Other components are just a plain markup with state</p>
<p>Visits dashboard page can be used for real-time displaying users & traffic data. It is a big vector map made with mapael in the center of this dashboard, that can display any region of the world with any data you want on hover action.</p>
<p>All of this component can be used on any page of the application.</p>
<p>
<Link className="btn btn-primary mr-sm" to="/app/main/analytics">Analytics</Link>
<Link className="btn btn-primary" to="/app/main/visits">Visits</Link>
</p>
</Widget>
<Widget id="E-Commerce">
<h3>E-commerce</h3>
<p className="alert alert-secondary font-weight-bold"><span className="text-warning">Important note.</span> This section is fully supported by <a
href="https://github.com/flatlogic/nodejs-backend" rel="noopener noreferrer" target="_blank">Node.js
backend</a> data.
</p>
<p>E-commerce is a group of three pages: product management, product list and product details. Must have a page if you are doing something similar to marketplace or shop.</p>
<p>&bull; Product management is a page, where you can manipulate with products data. You can CREATE, READ, UPDATE and DELETE products. <span className="small text-muted">(This page is available only in full stack version)</span></p>
<p>&bull; Products page is a list of ProductCard component. <code>ProductCard</code> component used to display product image, price, label, the small description in a proper way.</p>
<p>&bull; Product details is a detailed product card with a lot informative description.</p>
<p>Examples of <code>ProductCard</code> component:</p>
<Row>
<Col md={6}>
<ProductCard {...products[0]} />
</Col>
<Col md={6}>
<ProductCard {...products[2]} />
</Col>
</Row>
<p>
<Link className="btn btn-primary mr-sm" to="/app/ecommerce/management">Management</Link>
<Link className="btn btn-primary mr-sm" to="/app/ecommerce/products">List</Link>
<Link className="btn btn-primary" to="/app/ecommerce/product">Details</Link>
</p>
</Widget>
</Col>
<Col lg={3}>
<Scrollspy
title="PAGES"
prefix="pages"
ids={[
'Auth',
'Inbox',
'Dashboards',
'E-Commerce',
]} />
</Col>
</Row>
)
}
}
import React from "react";
import { HashLink as Link } from 'react-router-hash-link';
import Scrollspy from "react-scrollspy";
import s from '../styles.module.scss';
export default (props) => (
<div
className="border-left pl-4 d-md-down-none"
style={{
position: 'fixed',
overflowY: 'auto',
maxHeight: 'calc(100vh - 130px)',
paddingLeft: '15px'
}}
>
<h6 className="fw-semi-bold">{props.title}</h6>
<Scrollspy
items={props.ids}
currentClassName={s.activeScrollSpy}
offset={-170}
>
{props.ids.map((id) => (
<li key="id" className="mb-xs"><Link to={`/documentation/${props.prefix}#${id}`} className={s.scrollSpy}>{id.split('-').join(' ')}</Link></li>
))}
</Scrollspy>
</div>
)
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, Alert, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
const alerts = [{
id: 'al-1',
type: 'success',
msg: '<span class="fw-semi-bold">Success:</span> You successfully read this important alert message.',
visible: [true, true, true],
}, {
id: 'al-2',
type: 'info',
msg: '<span class="fw-semi-bold">Info:</span> This alert needs your attention, but it\'s not super important.',
visible: [true, true, true],
}, {
id: 'al-3',
type: 'warning',
msg: '<span class="fw-semi-bold"><strong>Warning:</strong></span> Best check yo self, you\'re not looking too good.',
visible: [true, true, true],
}, {
id: 'al-4',
type: 'danger',
msg: '<span class="fw-semi-bold">Danger:</span> Change this and that and try again. <a class="btn btn-default btn-xs float-right mr" href="#">Ignore</a> <a class="btn btn-danger btn-xs float-right mr-xs" href="#">Take this action</a>',
visible: [true, true, true],
}];
class Overview extends Component {
state = {
defaultAlertsTabId: '1',
transparentAlertsTabId: '1',
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Alerts</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Alerts</h2>
<p className="mb-lg">Provide contextual feedback messages for typical user actions with the handful of available and flexible alert messages.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Alert } from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultAlertsTabId === '1' })}
onClick={() => {
this.changeTab('defaultAlertsTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultAlertsTabId === '2' })}
onClick={() => {
this.changeTab('defaultAlertsTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultAlertsTabId}>
<TabPane tabId="1">
<p>Alerts are available for any length of text, as well as an optional dismiss button.</p>
{alerts.map((alert, index) => <Alert
key={alert.id} isOpen={alert.visible[0]} toggle={() => this.closeAlert(index, 0)}
color={alert.type}
>
<span dangerouslySetInnerHTML={{__html: alert.msg}}/>
</Alert>)}
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Alert\n' +
' isOpen={true}\n' +
' toggle={this.closeAlert}\n' +
' color="danger"\n' +
'>\n' +
' <h1>Alert Content</h1>\n' +
'</Alert>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
<Nav tabs className="bg-transparent">
<NavItem>
<NavLink
className={classnames({ active: this.state.transparentAlertsTabId === '1' })}
onClick={() => {
this.changeTab('transparentAlertsTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.transparentAlertsTabId === '2' })}
onClick={() => {
this.changeTab('transparentAlertsTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.transparentAlertsTabId}>
<TabPane tabId="1">
<p>Alerts are available for any length of text, as well as an optional dismiss button.</p>
{alerts.map((alert, index) => <Alert
className="alert-transparent"
key={alert.id} isOpen={alert.visible[0]} toggle={() => this.closeAlert(index, 0)}
color={alert.type}
>
<span dangerouslySetInnerHTML={{__html: alert.msg}}/>
</Alert>)}
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Alert\n' +
' className="alert-transparent"\n' +
' isOpen={true}\n' +
' toggle={this.closeAlert}\n' +
' color="danger"\n' +
'>\n' +
' <h1>Alert Content</h1>\n' +
'</Alert>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/alerts/" target="_blank" rel="noopener noreferrer">Reactstrap Alerts</a>
</Col>
</Row>
);
}
}
export default Overview;
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, Badge, Button, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class Badges extends Component {
state = {
defaultBadgesTabId: '1',
pillsBadgesTabId: '1',
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Badge</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Badge</h2>
<p className="mb-lg">Documentation and examples for badges, our small count and labeling component.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Badge } from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultBadgesTabId === '1' })}
onClick={() => {
this.changeTab('defaultBadgesTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultBadgesTabId === '2' })}
onClick={() => {
this.changeTab('defaultBadgesTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultBadgesTabId}>
<TabPane tabId="1">
<h1>Example heading <Badge color="primary">Primary</Badge></h1>
<h2>Example heading <Badge color="info">Info</Badge></h2>
<h3>Example heading <Badge color="warning">Warning</Badge></h3>
<h4>Example heading <Badge color="success">Success</Badge></h4>
<h5>Example heading <Badge color="danger">Danger</Badge></h5>
<h6>Example heading <Badge color="secondary">Secondary</Badge></h6>
<p>Badges can be used as part of links or buttons to provide a counter.</p>
<Button color="primary">Notifications <Badge color="danger">4</Badge></Button>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<h1>Example heading <Badge color="primary">Primary</Badge></h1>\n' +
'<h2>Example heading <Badge color="info">Info</Badge></h2>\n' +
'<h3>Example heading <Badge color="warning">Warning</Badge></h3>\n' +
'<h4>Example heading <Badge color="success">Success</Badge></h4>\n' +
'<h5>Example heading <Badge color="danger">Danger</Badge></h5>\n' +
'<h6>Example heading <Badge color="secondary">Secondary</Badge></h6>\n\n' +
'<Button color="primary">Notifications <Badge color="danger">4</Badge></Button>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
<Nav tabs className="bg-transparent">
<NavItem>
<NavLink
className={classnames({ active: this.state.pillsBadgesTabId === '1' })}
onClick={() => {
this.changeTab('pillsBadgesTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.pillsBadgesTabId === '2' })}
onClick={() => {
this.changeTab('pillsBadgesTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.pillsBadgesTabId}>
<TabPane tabId="1">
<h4>Pill badges</h4>
<p>
<Badge className="mr-xs" color="primary" pill>Primary</Badge>
<Badge className="mr-xs" color="info" pill>Info</Badge>
<Badge className="mr-xs" color="warning" pill>Warning</Badge>
<Badge className="mr-xs" color="success" pill>Success</Badge>
<Badge className="mr-xs" color="danger" pill>Danger</Badge>
<Badge className="mr-xs" color="secondary" pill>Secondary</Badge>
<Badge className="mr-xs" color="light" pill>Light</Badge>
<Badge className="mr-xs" color="dark" pill>Dark</Badge>
</p>
<h4>Badges with link</h4>
<p>
<Badge className="mr-xs" href="#" color="primary">Primary</Badge>
<Badge className="mr-xs" href="#" color="info">Info</Badge>
<Badge className="mr-xs" href="#" color="warning">Warning</Badge>
<Badge className="mr-xs" href="#" color="success">Success</Badge>
<Badge className="mr-xs" href="#" color="danger">Danger</Badge>
<Badge className="mr-xs" href="#" color="secondary">Secondary</Badge>
<Badge className="mr-xs" href="#" color="light">Light</Badge>
<Badge className="mr-xs" href="#" color="dark">Dark</Badge>
</p>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>
{'<Badge className="mr-xs" color="primary" pill>Primary</Badge> \n' +
'<Badge className="mr-xs" href="#" color="primary">Primary</Badge>'}
</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/badge/" target="_blank" rel="noopener noreferrer">Reactstrap Badge</a>
</Col>
</Row>
);
}
}
export default Badges;
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, Button, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class Buttons extends Component {
state = {
defaultButtonTabId: '1',
outlineButtonsTabId: '1',
buttonsSizeTabId: '1'
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Buttons</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Buttons</h2>
<p className="mb-lg">Bootstrap includes several predefined button styles, each serving its own semantic purpose, with a few extras thrown in for more control.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Button } from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultButtonTabId === '1' })}
onClick={() => {
this.changeTab('defaultButtonTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultButtonTabId === '2' })}
onClick={() => {
this.changeTab('defaultButtonTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultButtonTabId}>
<TabPane tabId="1">
<Button color="default" className="width-100 mb-xs mr-xs">Default</Button>
<Button color="primary" className="width-100 mb-xs mr-xs">Primary</Button>
<Button color="info" className="width-100 mb-xs mr-xs">Info</Button>
<Button color="success" className="width-100 mb-xs mr-xs">Success</Button>
<Button color="warning" className="width-100 mb-xs mr-xs">Warning</Button>
<Button color="danger" className="width-100 mb-xs mr-xs">Danger</Button>
<Button color="gray" className="width-100 mb-xs mr-xs">Gray</Button>
<Button color="inverse" className="width-100 mb-xs mr-xs">Inverse</Button>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Button color="default" className="width-100 mb-xs mr-xs">Default</Button>\n' +
'<Button color="primary">Primary</Button>\n' +
'<Button color="info">Info</Button>\n' +
'<Button color="success">Success</Button>\n' +
'<Button color="warning"">Warning</Button>\n' +
'<Button color="danger">Danger</Button>\n' +
'<Button color="gray">Gray</Button>\n' +
'<Button color="inverse">Inverse</Button>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
<Nav tabs className="bg-transparent">
<NavItem>
<NavLink
className={classnames({ active: this.state.outlineButtonsTabId === '1' })}
onClick={() => {
this.changeTab('outlineButtonsTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.outlineButtonsTabId === '2' })}
onClick={() => {
this.changeTab('outlineButtonsTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.outlineButtonsTabId}>
<TabPane tabId="1">
<Button outline color="default" className="width-100 mb-xs mr-xs">Default</Button>
<Button outline color="primary" className="width-100 mb-xs mr-xs">Primary</Button>
<Button outline color="info" className="width-100 mb-xs mr-xs">Info</Button>
<Button outline color="success" className="width-100 mb-xs mr-xs">Success</Button>
<Button outline color="warning" className="width-100 mb-xs mr-xs">Warning</Button>
<Button outline color="danger" className="width-100 mb-xs mr-xs">Danger</Button>
<Button outline color="gray" className="width-100 mb-xs mr-xs">Gray</Button>
<Button outline color="inverse" className="width-100 mb-xs mr-xs">Inverse</Button>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>
{'<Button outline color="default">Default</Button>\n' +
'<Button outline color="primary">Primary</Button>\n' +
'<Button outline color="info">Info</Button>\n' +
'<Button outline color="success">Success</Button>\n' +
'<Button outline color="warning">Warning</Button>\n' +
'<Button outline color="danger">Danger</Button>\n' +
'<Button outline color="gray"">Gray</Button>\n' +
'<Button outline color="inverse">Inverse</Button>'}
</SyntaxHighlighter>
</TabPane>
</TabContent>
<Nav tabs className="bg-transparent">
<NavItem>
<NavLink
className={classnames({ active: this.state.buttonsSizeTabId === '1' })}
onClick={() => {
this.changeTab('buttonsSizeTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.buttonsSizeTabId === '2' })}
onClick={() => {
this.changeTab('buttonsSizeTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.buttonsSizeTabId}>
<TabPane tabId="1">
<p className="fs-mini text-muted">
Fancy larger or smaller buttons?
Four separate sizes available for all use cases:
from tiny 10px button to large one.
</p>
<p>
<Button color="default" size="lg" className="mb-xs mr-xs">Large button</Button>
<Button color="primary" className="mb-xs mr-xs">Default button</Button>
<Button color="info" size="sm" className="mb-xs mr-xs">Small button</Button>
<Button color="success" size="xs" className="mb-xs mr-xs">Tiny button</Button>
</p>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>
{'<Button color="default" size="lg">Large button</Button>\n' +
'<Button color="primary">Default button</Button>\n' +
'<Button color="info" size="sm">Small button</Button>\n' +
'<Button color="success" size="xs">Tiny button</Button>'}
</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/buttons/" target="_blank" rel="noopener noreferrer">Reactstrap Buttons</a>
</Col>
</Row>
);
}
}
export default Buttons;
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, Button, Card, CardBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class Buttons extends Component {
state = {
defaultCardTabId: '1',
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Card</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Card</h2>
<p className="mb-lg">Cards support a wide variety of content, including images, text, list groups, links, and more. Below are examples of whats supported.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Card, CardBody } from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultCardTabId === '1' })}
onClick={() => {
this.changeTab('defaultCardTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultCardTabId === '2' })}
onClick={() => {
this.changeTab('defaultCardTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultCardTabId}>
<TabPane tabId="1">
<Card className="border-0">
<CardBody>
<button className="btn-link fw-semi-bold text-success">Avg Rating</button>
<button className="btn-link fw-semi-bold text-muted ml-sm">All Time</button>
<hr />
<div className="d-flex justify-content-between mb-lg">
<div className="text-warning">
<i className="fa fa-star mr-xs" />
<i className="fa fa-star mr-xs" />
<i className="fa fa-star mr-xs" />
<i className="fa fa-star mr-xs" />
<i className="fa fa-star" />
</div>
<span className="text-muted"><small>342 REVIEWS</small></span>
</div>
<div className="mb-lg">
<h3 className="text-success mb-0">69%</h3>
of customers recomend this product
</div>
<Button className="btn-rounded-f" color="success">Write a Review</Button>
</CardBody>
</Card>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Card className="border-0">\n' +
' <CardBody>\n' +
' <button className="btn-link fw-semi-bold text-success">Avg Rating</button>\n' +
' <button className="btn-link fw-semi-bold text-muted ml-sm">All Time</button>\n' +
' <hr />\n' +
' <div className="d-flex justify-content-between mb-lg">\n' +
' <div className="text-warning">\n' +
' <i className="fa fa-star mr-xs" />\n' +
' <i className="fa fa-star mr-xs" />\n' +
' <i className="fa fa-star mr-xs" />\n' +
' <i className="fa fa-star mr-xs" />\n' +
' <i className="fa fa-star" />\n' +
' </div>\n' +
' <span className="text-muted"><small>342 REVIEWS</small></span>\n' +
' </div>\n' +
' <div className="mb-lg">\n' +
' <h3 className="text-success mb-0">69%</h3>\n' +
' of customers recomend this product\n' +
' </div>\n' +
' <Button className="btn-rounded-f" color="success">Write a Review</Button>\n' +
' </CardBody>\n' +
'</Card>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/card/" target="_blank" rel="noopener noreferrer">Reactstrap Card</a>
</Col>
</Row>
);
}
}
export default Buttons;
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, UncontrolledCarousel } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
import firstSlide from '../../../images/slides/1.jpg';
import secondSlide from '../../../images/slides/2.jpg';
import thirdSlide from '../../../images/slides/3.jpg';
const carouselItems = [
{ src: firstSlide, caption: '' },
{ src: secondSlide, caption: '' },
{ src: thirdSlide, caption: '' },
];
class Buttons extends Component {
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Carousel</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Carousel</h2>
<p className="mb-lg">A slideshow component for cycling through elementsimages or slides of textlike a carousel.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { UncontrolledCarousel} from 'reactstrap';"}
</SyntaxHighlighter>
<UncontrolledCarousel className="mb-lg mt-lg" captionTex={null} items={carouselItems} />
<SyntaxHighlighter language='javascript' style={tomorrow}>{'const carouselItems = [\n' +
' { src: firstSlide, caption: \'\' },\n' +
' { src: secondSlide, caption: \'\' },\n' +
' { src: thirdSlide, caption: \'\' },\n' +
'];\n' +
'\n' +
'<UncontrolledCarousel captionTex={null} items={carouselItems} />'}
</SyntaxHighlighter>
For more examples please refer to <a href="https://reactstrap.github.io/components/carousel/" target="_blank"
rel="noopener noreferrer">Reactstrap Carousel</a>
</Col>
</Row>
);
}
}
export default Buttons;
This diff is collapsed. Click to expand it.
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class NavPage extends Component {
state = {
defaultNavTabId: '1',
verticalNavTabId: '1',
pillsNavTabId: '1',
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Nav</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Nav</h2>
<p className="mb-lg">Change the style of Nav component with modifiers and utilities. Mix and match as needed, or build your own.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Nav, NavItem, NavLink } from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultNavTabId === '1' })}
onClick={() => {
this.changeTab('defaultNavTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultNavTabId === '2' })}
onClick={() => {
this.changeTab('defaultNavTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultNavTabId}>
<TabPane tabId="1">
<Nav>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Another Link</NavLink>
</NavItem>
<NavItem>
<NavLink disabled href="#">Disabled Link</NavLink>
</NavItem>
</Nav>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Nav>\n' +
' <NavItem>\n' +
' <NavLink href="#">Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink href="#">Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink href="#">Another Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink disabled href="#">Disabled Link</NavLink>\n' +
' </NavItem>\n' +
'</Nav>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.verticalNavTabId === '1' })}
onClick={() => {
this.changeTab('verticalNavTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.verticalNavTabId === '2' })}
onClick={() => {
this.changeTab('verticalNavTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.verticalNavTabId}>
<TabPane tabId="1">
<Nav vertical>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Another Link</NavLink>
</NavItem>
<NavItem>
<NavLink disabled href="#">Disabled Link</NavLink>
</NavItem>
</Nav>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Nav vertical>\n' +
' <NavItem>\n' +
' <NavLink href="#">Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink href="#">Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink href="#">Another Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink disabled href="#">Disabled Link</NavLink>\n' +
' </NavItem>\n' +
'</Nav>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.pillsNavTabId === '1' })}
onClick={() => {
this.changeTab('pillsNavTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.pillsNavTabId === '2' })}
onClick={() => {
this.changeTab('pillsNavTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.pillsNavTabId}>
<TabPane tabId="1">
<Nav pills>
<NavItem>
<NavLink href="#" active>Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Another Link</NavLink>
</NavItem>
<NavItem>
<NavLink disabled href="#">Disabled Link</NavLink>
</NavItem>
</Nav>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Nav>\n' +
' <NavItem pills>\n' +
' <NavLink href="#" active>Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink href="#">Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink href="#">Another Link</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink disabled href="#">Disabled Link</NavLink>\n' +
' </NavItem>\n' +
'</Nav>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/card/" target="_blank" rel="noopener noreferrer">Reactstrap Card</a>
</Col>
</Row>
);
}
}
export default NavPage;
import React, { Component } from 'react';
import {
Row,
Col,
Breadcrumb,
BreadcrumbItem,
TabContent,
TabPane,
Nav,
NavItem,
NavLink,
Navbar,
NavbarBrand,
NavbarToggler,
Collapse,
UncontrolledDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem
} from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class NavbarPage extends Component {
state = {
defaultNavTabId: '1',
verticalNavTabId: '1',
pillsNavTabId: '1',
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Navbar</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Navbar</h2>
<p className="mb-lg">Documentation and examples for Bootstraps powerful, responsive navigation header, the navbar.
Includes support for branding, navigation, and more, including support for our collapse plugin.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import {\n" +
" Nav,\n" +
" NavItem,\n" +
" NavLink,\n" +
" Navbar,\n" +
" NavbarBrand,\n" +
" NavbarToggler,\n" +
" Collapse,\n" +
" UncontrolledDropdown,\n" +
" DropdownToggle,\n" +
" DropdownMenu,\n" +
" DropdownItem\n" +
"} from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultNavTabId === '1' })}
onClick={() => {
this.changeTab('defaultNavTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultNavTabId === '2' })}
onClick={() => {
this.changeTab('defaultNavTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultNavTabId}>
<TabPane tabId="1">
<Navbar color="light" light expand="md">
<NavbarBrand href="/">Sing</NavbarBrand>
<NavbarToggler />
<Collapse navbar>
<Nav className="ml-auto" navbar>
<NavItem>
<NavLink href="#">Components</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Documentation</NavLink>
</NavItem>
<UncontrolledDropdown nav inNavbar>
<DropdownToggle nav caret>
Options
</DropdownToggle>
<DropdownMenu right>
<DropdownItem>
Option 1
</DropdownItem>
<DropdownItem>
Option 2
</DropdownItem>
<DropdownItem divider />
<DropdownItem>
Reset
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</Collapse>
</Navbar>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Navbar color="light" light expand="md">\n' +
' <NavbarBrand href="/">Sing</NavbarBrand>\n' +
' <NavbarToggler />\n' +
' <Collapse navbar>\n' +
' <Nav className="ml-auto" navbar>\n' +
' <NavItem>\n' +
' <NavLink href="#">Components</NavLink>\n' +
' </NavItem>\n' +
' <NavItem>\n' +
' <NavLink href="#">Documentation</NavLink>\n' +
' </NavItem>\n' +
' <UncontrolledDropdown nav inNavbar>\n' +
' <DropdownToggle nav caret>\n' +
' Options\n' +
' </DropdownToggle>\n' +
' <DropdownMenu right>\n' +
' <DropdownItem>\n' +
' Option 1\n' +
' </DropdownItem>\n' +
' <DropdownItem>\n' +
' Option 2\n' +
' </DropdownItem>\n' +
' <DropdownItem divider />\n' +
' <DropdownItem>\n' +
' Reset\n' +
' </DropdownItem>\n' +
' </DropdownMenu>\n' +
' </UncontrolledDropdown>\n' +
' </Nav>\n' +
' </Collapse>\n' +
'</Navbar>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/card/" target="_blank" rel="noopener noreferrer">Reactstrap Card</a>
</Col>
</Row>
);
}
}
export default NavbarPage;
import React, { Component } from 'react';
import {
Row,
Col,
Breadcrumb,
BreadcrumbItem,
TabContent,
TabPane,
Nav,
NavItem,
NavLink,
Button,
Popover,
PopoverHeader,
PopoverBody,
UncontrolledTooltip,
} from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class NavbarPage extends Component {
state = {
defaultPopoversTabId: '1',
defaultTooltipsTabId: '1',
popovers: {
1: false,
2: false,
3: false,
4: false,
}
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
toggle(id) {
this.setState(prevState => ({
popovers: {
...prevState.popovers,
[id]: !prevState.popovers[id],
},
}))
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Popovers & Tooltips</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Popovers</h2>
<p className="mb-lg">The Popover is similar to Tooltip; it is a pop-up box that appears when the user clicks on an element. The difference is that the popover can contain much more content.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Popover, PopoverHeader, PopoverBody, UncontrolledTooltip } from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultPopoversTabId === '1' })}
onClick={() => {
this.changeTab('defaultPopoversTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultPopoversTabId === '2' })}
onClick={() => {
this.changeTab('defaultPopoversTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultPopoversTabId}>
<TabPane tabId="1">
<Button className="mr" id="popover-1" type="button" color="success" onClick={() => this.toggle(1)}>
Bottom
</Button>
<Button className="mr" id="popover-2" type="button" color="danger" onClick={() => this.toggle(2)}>
Right
</Button>
<Button className="mr" id="popover-3" type="button" color="warning" onClick={() => this.toggle(3)}>
Top
</Button>
<Button className="mr" id="popover-4" type="button" color="info" onClick={() => this.toggle(4)}>
Left
</Button>
<Popover placement="bottom" isOpen={this.state.popovers[1]} target="popover-1" toggle={() => this.toggle(1)}>
<PopoverHeader>Popover Title</PopoverHeader>
<PopoverBody>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</PopoverBody>
</Popover>
<Popover placement="right" isOpen={this.state.popovers[2]} target="popover-2" toggle={() => this.toggle(2)}>
<PopoverHeader>Popover Title</PopoverHeader>
<PopoverBody>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</PopoverBody>
</Popover>
<Popover placement="top" isOpen={this.state.popovers[3]} target="popover-3" toggle={() => this.toggle(3)}>
<PopoverHeader>Popover Title</PopoverHeader>
<PopoverBody>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</PopoverBody>
</Popover>
<Popover placement="left" isOpen={this.state.popovers[4]} target="popover-4" toggle={() => this.toggle(4)}>
<PopoverHeader>Popover Title</PopoverHeader>
<PopoverBody>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</PopoverBody>
</Popover>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Button id="popover" type="button" color="info" onClick={this.toggle}>\n' +
' Top\n' +
'</Button>\n\n' +
'<Popover placement="top" isOpen={this.state.isPopoverActive} target="popover" toggle={this.toggle}>\n' +
' <PopoverHeader>Popover Title</PopoverHeader>\n' +
' <PopoverBody>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</PopoverBody>\n' +
'</Popover>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
<h2>Tooltips</h2>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultTooltipsTabId === '1' })}
onClick={() => {
this.changeTab('defaultTooltipsTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultTooltipsTabId === '2' })}
onClick={() => {
this.changeTab('defaultTooltipsTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultTooltipsTabId}>
<TabPane tabId="1">
<Button className="mr" id="tooltip-1" type="button" color="success">
Bottom
</Button>
<Button className="mr" id="tooltip-2" type="button" color="danger">
Right
</Button>
<Button className="mr" id="tooltip-3" type="button" color="warning">
Top
</Button>
<Button className="mr" id="tooltip-4" type="button" color="info">
Left
</Button>
<UncontrolledTooltip placement="bottom" target="tooltip-1">
Hello world!
</UncontrolledTooltip>
<UncontrolledTooltip placement="right" target="tooltip-2">
Hello world!
</UncontrolledTooltip>
<UncontrolledTooltip placement="top" target="tooltip-3">
Hello world!
</UncontrolledTooltip>
<UncontrolledTooltip placement="left" target="tooltip-4">
Hello world!
</UncontrolledTooltip>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<Button className="mr" id="tooltip" type="button" color="info">\n' +
' Left\n' +
'</Button>\n\n' +
'<UncontrolledTooltip placement="left" target="tooltip">\n' +
' Hello world!\n' +
'</UncontrolledTooltip>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/popovers/" target="_blank" rel="noopener noreferrer">Reactstrap Popovers</a>
&nbsp;and <a href="https://reactstrap.github.io/components/tooltips/" target="_blank" rel="noopener noreferrer">Reactstrap Tooltips</a>
</Col>
</Row>
);
}
}
export default NavbarPage;
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, Progress, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class Buttons extends Component {
state = {
defaultProgressTabId: '1',
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Progress</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Progress</h2>
<p className="mb-lg">Cards support a wide variety of content, including images, text, list groups, links, and more. Below are examples of whats supported.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Progress } from 'reactstrap';"}
</SyntaxHighlighter>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultProgressTabId === '1' })}
onClick={() => {
this.changeTab('defaultProgressTabId', '1');
}}
>
Example
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultProgressTabId === '2' })}
onClick={() => {
this.changeTab('defaultProgressTabId', '2');
}}
>
Code
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultProgressTabId}>
<TabPane tabId="1">
<div className="text-center">0%</div>
<Progress />
<div className="text-center">25%</div>
<Progress value="25" />
<div className="text-center">50%</div>
<Progress value={50} />
<div className="text-center">75%</div>
<Progress striped value={75} />
<div className="text-center">100%</div>
<Progress animated value="100" />
<div className="text-center">Multiple bars</div>
<Progress multi>
<Progress bar value="15" />
<Progress bar color="success" value="30" />
<Progress bar color="info" value="25" />
<Progress bar color="warning" value="20" />
<Progress bar color="danger" value="5" />
</Progress>
</TabPane>
<TabPane tabId="2">
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<div className="text-center">0%</div>\n' +
'<Progress />\n' +
'<div className="text-center">25%</div>\n' +
'<Progress value="25" />\n' +
'<div className="text-center">50%</div>\n' +
'<Progress value={50} />\n' +
'<div className="text-center">75%</div>\n' +
'<Progress striped value={75} />\n' +
'<div className="text-center">100%</div>\n' +
'<Progress animated value="100" />\n' +
'<div className="text-center">Multiple bars</div>\n' +
'<Progress multi>\n' +
' <Progress bar value="15" />\n' +
' <Progress bar color="success" value="30" />\n' +
' <Progress bar color="info" value="25" />\n' +
' <Progress bar color="warning" value="20" />\n' +
' <Progress bar color="danger" value="5" />\n' +
'</Progress>'}</SyntaxHighlighter>
</TabPane>
</TabContent>
For more examples please refer to <a href="https://reactstrap.github.io/components/progress/" target="_blank" rel="noopener noreferrer">Reactstrap Progress</a>
</Col>
</Row>
);
}
}
export default Buttons;
import React, { Component } from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, Collapse, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/prism';
import classnames from 'classnames';
import { tomorrow } from 'react-syntax-highlighter/dist/styles/prism';
class Buttons extends Component {
state = {
defaultTabsTabId: '1',
accordion: [false, false, false],
};
changeTab(field, id) {
this.setState({
[field]: id,
})
}
toggleAccordion(id) {
const arr = [];
arr.length = this.state.accordion.length;
arr.fill(false);
arr[id] = !this.state.accordion[id];
this.setState({
accordion: arr,
});
}
render() {
return (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Components</BreadcrumbItem>
<BreadcrumbItem active>Tabs & Accordion</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<h2>Tabs</h2>
<p className="mb-lg">Activates a tab element and content container.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { TabContent, TabPane } from 'reactstrap';"}
</SyntaxHighlighter>
<h4 className="mt-lg">Example</h4>
<Nav tabs className="bg-transparent mt">
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultTabsTabId === '1' })}
onClick={() => {
this.changeTab('defaultTabsTabId', '1');
}}
>
Tab 1
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: this.state.defaultTabsTabId === '2' })}
onClick={() => {
this.changeTab('defaultTabsTabId', '2');
}}
>
Tab 2
</NavLink>
</NavItem>
</Nav>
<TabContent className="mb-xlg" activeTab={this.state.defaultTabsTabId}>
<TabPane tabId="1">
First tab content
</TabPane>
<TabPane tabId="2">
Second tab content
</TabPane>
</TabContent>
<h4>Code</h4>
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<TabContent className="mb-xlg" activeTab={this.state.activeTabId}>\n' +
' <TabPane tabId="1">\n' +
' First tab content\n' +
' </TabPane>\n' +
' <TabPane tabId="2">\n' +
' Second tab content\n' +
' </TabPane>\n' +
'</TabContent>'}</SyntaxHighlighter>
For more examples please refer to <a href="https://reactstrap.github.io/components/tabs/"
rel="noopener noreferrer" target="_blank">Reactstrap Tabs</a>
<h2 className="mt-lg">Accordion</h2>
<p className="mb-lg">Activates a tab element and content container.</p>
<SyntaxHighlighter language='javascript' style={tomorrow}>
{"import { Collapse } from 'reactstrap';"}
</SyntaxHighlighter>
<h4 className="mt-lg">Example</h4>
<div className="card panel mt-lg mb-xs">
{ /* eslint-disable */ }
<div
className="card-header panel-header bg-light" role="button"
onClick={() => { this.toggleAccordion(0); }}
>
{ /* eslint-enable */ }
<div className="mb-0">
{/* eslint-disable-next-line */}
<a className="accordion-toggle" role="button">
Collapsible Group Item
<i className={`fa fa-angle-down ${this.state.accordion[0] ? 'expanded' : ''}`} />
</a>
</div>
</div>
<Collapse className="panel-body" isOpen={this.state.accordion[0]}>
<p>Get base styles and flexible support for collapsible components like accordions and navigation.
Using the collapse plugin, we built a simple accordion by extending the panel component.
</p>
</Collapse>
</div>
<div className="card panel mb-xs">
{ /* eslint-disable */ }
<div
className="card-header panel-header bg-light" role="button"
onClick={() => { this.toggleAccordion(1); }}
>
{ /* eslint-enable */ }
<div className="mb-0">
{/* eslint-disable-next-line */}
<a className="accordion-toggle" role="button">
Normal Text Insertion
<i className={`fa fa-angle-down ${this.state.accordion[1] ? 'expanded' : ''}`} />
</a>
</div>
</div>
<Collapse className="panel-body" isOpen={this.state.accordion[1]}>
<p>Why don't use Lore Ipsum? I think if some one says don't use lore ipsum it's very controversial point. I think the opposite actually.
</p>
</Collapse>
</div>
<div className="card panel mb-lg">
{ /* eslint-disable */ }
<div
className="card-header panel-header bg-light" role="button"
onClick={() => { this.toggleAccordion(2); }}
>
{ /* eslint-enable */ }
<div className="mb-0">
{/* eslint-disable-next-line */}
<a className="accordion-toggle" role="button">
Random from the Web
<i className={`fa fa-angle-down ${this.state.accordion[2] ? 'expanded' : ''}`} />
</a>
</div>
</div>
<Collapse className="panel-body" isOpen={this.state.accordion[2]}>
<p><span className="fw-semi-bold">Light Blue</span> - is a next generation admin template based
on the latest Metro design. There are few reasons we want to tell you, why we have created it:
We didn't like the darkness of most of admin templates, so we created this light one.
We didn't like the high contrast of most of admin templates, so we created this unobtrusive one.
We searched for a solution of how to make widgets look like real widgets, so we decided that
deep background - is what makes widgets look real.
</p>
<p className="no-margin text-muted"><em>- Some One</em></p>
</Collapse>
</div>
<h4>Code</h4>
<SyntaxHighlighter language='javascript' style={tomorrow}>{'<div className="card panel mb-xs">\n' +
' <div\n' +
' className="card-header panel-header bg-light" role="button"\n' +
' onClick={this.toggleAccordion}\n' +
' >\n' +
' <div className="mb-0">\n' +
' <a className="accordion-toggle" role="button">\n' +
' Normal Text Insertion\n' +
' <i className={["fa fa-angle-down", this.state.isAccordionOpened ? "expanded" : ""].join(" ")} />\n' +
' </a>\n' +
' </div>\n' +
' </div>\n' +
' <Collapse className="panel-body" isOpen={this.state.isAccordionOpened}>\n' +
' <p>Why don\'t use Lore Ipsum? I think if some one says don\'t use lore ipsum it\'s very controversial point. I think the opposite actually.\n' +
' </p>\n' +
' </Collapse>\n' +
'</div>'}</SyntaxHighlighter>
For more examples please refer to <a href="https://reactstrap.github.io/components/collapse/" target="_blank" rel="noopener noreferrer">Reactstrap Collapse</a>
</Col>
</Row>
);
}
}
export default Buttons;
import React from 'react';
import { Row, Col, Breadcrumb, BreadcrumbItem, Table } from 'reactstrap';
import Widget from '../../../components/Widget/Widget';
import Scrollspy from "../ScrollSpyComponent";
const Licences = () => (
<Row>
<Col md={10}>
<Breadcrumb>
<BreadcrumbItem>YOU ARE HERE</BreadcrumbItem>
<BreadcrumbItem>Documentation</BreadcrumbItem>
<BreadcrumbItem>Getting Started</BreadcrumbItem>
<BreadcrumbItem active>Licences</BreadcrumbItem>
</Breadcrumb>
</Col>
<Col lg={9}>
<Widget id="Licences">
<h2>Licences</h2>
<p className="lead">
A license grants you a non-exclusive and non-transferable right to use
and incorporate the item in your personal or commercial projects.
If your end product including an item is going to be free to the end user then
a Single License is what you need. An Extended License is required if the
end user must pay to use the end product.
</p>
<Table>
<thead>
<tr>
<th></th>
<th>Single</th>
<th>Extended</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hundreds unique components</td>
<td className="text-success fw-bold">+</td>
<td className="text-success fw-bold">+</td>
</tr>
<tr>
<td>All pages</td>
<td className="text-success fw-bold">+</td>
<td className="text-success fw-bold">+</td>
</tr>
<tr>
<td>Free Updates</td>
<td>3 months</td>
<td>6 months</td>
</tr>
<tr>
<td>Paying users allowed</td>
<td className="text-danger fw-bold">-</td>
<td className="text-success fw-bold">+</td>
</tr>
</tbody>
</Table>
</Widget>
<Widget id="Single">
<h3>Single Application License</h3>
<p className="lead">
Your use of the item is restricted to a single application. You may use the item
in work which you are creating for your own purposes or for your client. You must
not incorporate the item in a work which is created for redistribution or resale
by you or your client. The item may not be redistributed or resold. You may not
charge users for using your application.
</p>
</Widget>
<Widget id="Extended">
<h3>Extended Application License</h3>
<p className="lead">
Your use of the item is restricted to a single application.
You may use the item in work which you are creating for your own
purposes or for your clients. You are licensed to use the Item to create one single
End Product for yourself or for one client (a single application), and the
End Product may be Sold and users may be charged for using it (e.g. you are building
SAAS application).
</p>
</Widget>
<p class="mt">
In case if you need any clarifications considering licenses feel free
to contact us via email: <a class="text-warning" href="mailto:support@flatlogic.com">support@flatlogic.com</a>.
</p>
</Col>
<Col lg={3}>
<Scrollspy
title="LICENCES"
prefix="getting-started/licences"
ids={[
'Licences',
'Single',
'Extended',
]} />
</Col>
</Row>
);
export default Licences;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.