Simplify code by not using classes when they aren't needed

Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
This commit is contained in:
Mcat12
2017-07-30 15:37:54 -04:00
parent a69976ad4a
commit fb525c47a2
15 changed files with 383 additions and 419 deletions

View File

@@ -1,11 +1,7 @@
import React, { Component } from 'react';
import React from 'react';
export default class Aside extends Component {
render() {
return (
<aside className="aside-menu">
Aside Menu
</aside>
)
}
}
export default () => (
<aside className="aside-menu">
Aside Menu
</aside>
);

View File

@@ -1,20 +1,16 @@
import React, { Component } from 'react';
import React from 'react';
export default class Footer extends Component {
render() {
return (
<footer className="app-footer">
<div className="pull-right hidden-xs">
<b>Pi-hole Version </b> <span id="piholeVersion">vDev </span>
<b>Web Interface Version </b> <span id="webVersion">vDev</span>
</div>
<div>
<i className="fa fa-github"/> <strong>
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=3J2L3Z4DHW9UY">
Donate
</a></strong> if you found this useful
</div>
</footer>
)
}
}
export default () => (
<footer className="app-footer">
<div className="pull-right hidden-xs">
<b>Pi-hole Version </b> <span id="piholeVersion">vDev </span>
<b>Web Interface Version </b> <span id="webVersion">vDev</span>
</div>
<div>
<i className="fa fa-github"/> <strong>
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=3J2L3Z4DHW9UY">
Donate
</a></strong> if you found this useful
</div>
</footer>
);

View File

@@ -3,60 +3,60 @@ import { Line } from 'react-chartjs-2';
import { padNumber, parseObjectForGraph, api, makeCancelable } from '../../utils';
export default class ForwardDestOverTime extends Component {
state = {
data: {
labels: [],
datasets: []
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: tooltipItem => {
const label = tooltipItem[0].xLabel;
const time = label.match(/(\d?\d):?(\d?\d?)/);
const h = parseInt(time[1], 10);
const m = parseInt(time[2], 10) || 0;
const from = padNumber(h)+":"+padNumber(m-5)+":00";
const to = padNumber(h)+":"+padNumber(m+4)+":59";
return "Forward destinations from "+from+" to "+to;
},
label: (tooltipItems, data) => {
return data.datasets[tooltipItems.datasetIndex].label + ": " + (100.0*tooltipItems.yLabel).toFixed(1) + "%";
}
}
},
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "hour",
displayFormats: {
hour: "HH:mm"
},
tooltipFormat: "HH:mm"
}
}],
yAxes: [{
ticks: {
mix: 0.0,
max: 1.0,
beginAtZero: true,
callback: (value, index, values) => Math.round(value*100) + "%"
},
stacked: true
}]
},
maintainAspectRatio: true
}
};
constructor(props) {
super(props);
this.state = {
data: {
labels: [],
datasets: []
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: (tooltipItem, data) => {
const label = tooltipItem[0].xLabel;
const time = label.match(/(\d?\d):?(\d?\d?)/);
const h = parseInt(time[1], 10);
const m = parseInt(time[2], 10) || 0;
const from = padNumber(h)+":"+padNumber(m-5)+":00";
const to = padNumber(h)+":"+padNumber(m+4)+":59";
return "Forward destinations from "+from+" to "+to;
},
label: (tooltipItems, data) => {
return data.datasets[tooltipItems.datasetIndex].label + ": " + (100.0*tooltipItems.yLabel).toFixed(1) + "%";
}
}
},
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "hour",
displayFormats: {
hour: "HH:mm"
},
tooltipFormat: "HH:mm"
}
}],
yAxes: [{
ticks: {
mix: 0.0,
max: 1.0,
beginAtZero: true,
callback: (value, index, values) => Math.round(value*100) + "%"
},
stacked: true
}]
},
maintainAspectRatio: true
}
};
this.updateGraph = this.updateGraph.bind(this);
}
@@ -128,9 +128,7 @@ export default class ForwardDestOverTime extends Component {
data.labels = labels;
data.datasets = datasets;
this.setState({
data: data
});
this.setState({ data });
})
.catch(() => null);
}

View File

@@ -1,47 +1,42 @@
import React, { Component } from 'react';
import React from 'react';
export default class Header extends Component {
//const sidebarToggle = (e) => {
// e.preventDefault();
// document.body.classList.toggle('sidebar-hidden');
//};
sidebarToggle(e) {
e.preventDefault();
document.body.classList.toggle('sidebar-hidden');
}
const sidebarMinimize = (e) => {
e.preventDefault();
document.body.classList.toggle('sidebar-minimized');
};
sidebarMinimize(e) {
e.preventDefault();
document.body.classList.toggle('sidebar-minimized');
}
const mobileSidebarToggle = (e) => {
e.preventDefault();
document.body.classList.toggle('sidebar-mobile-show');
};
mobileSidebarToggle(e) {
e.preventDefault();
document.body.classList.toggle('sidebar-mobile-show');
}
//const asideToggle = (e) => {
// e.preventDefault();
// document.body.classList.toggle('aside-menu-hidden');
//};
asideToggle(e) {
e.preventDefault();
document.body.classList.toggle('aside-menu-hidden');
}
render() {
return (
<header className="app-header navbar">
<button className="navbar-toggler mobile-sidebar-toggler d-lg-none" onClick={this.mobileSidebarToggle} type="button">&#9776;</button>
<a className="navbar-brand" href="https://pi-hole.net">
<span style={{color: "white", paddingLeft: "45px", lineHeight: "40px"}}>
Pi-<b>hole</b>
</span>
</a>
<ul className="nav navbar-nav d-md-down-none mr-auto">
<li className="nav-item">
<button className="nav-link navbar-toggler sidebar-toggler" type="button" onClick={this.sidebarToggle}>&#9776;</button>
</li>
</ul>
<div className="navbar-custom-menu">
<ul className="nav navbar-nav">
<li className="dropdown user user-menu userBox"/>
</ul>
</div>
</header>
)
}
}
export default () => (
<header className="app-header navbar">
<button className="navbar-toggler mobile-sidebar-toggler d-lg-none" onClick={mobileSidebarToggle} type="button">&#9776;</button>
<a className="navbar-brand" href="https://pi-hole.net">
<span style={{color: "white", paddingLeft: "45px", lineHeight: "40px"}}>
Pi-<b>hole</b>
</span>
</a>
<ul className="nav navbar-nav d-md-down-none mr-auto">
<li className="nav-item">
<button className="nav-link navbar-toggler sidebar-toggler" type="button" onClick={sidebarMinimize}>&#9776;</button>
</li>
</ul>
<div className="navbar-custom-menu">
<ul className="nav navbar-nav">
<li className="dropdown user user-menu userBox"/>
</ul>
</div>
</header>
);

View File

@@ -3,94 +3,93 @@ import { Line } from 'react-chartjs-2';
import { padNumber, parseObjectForGraph, api, makeCancelable } from '../../utils';
export default class QueriesGraph extends Component {
state = {
data: {
labels: [],
datasets: [
{
label: "Total Queries",
data: [],
fill: true,
backgroundColor: "rgba(220,220,220,0.5)",
borderColor: "rgba(0, 166, 90,.8)",
pointBorderColor: "rgba(0, 166, 90,.8)",
pointRadius: 1,
pointHoverRadius: 5,
pointHitRadius: 5,
cubicInterpolationMode: "monotone"
},
{
label: "Blocked Queries",
data: [],
fill: true,
backgroundColor: "rgba(0,192,239,0.5)",
borderColor: "rgba(0,192,239,1)",
pointBorderColor: "rgba(0,192,239,1)",
pointRadius: 1,
pointHoverRadius: 5,
pointHitRadius: 5,
cubicInterpolationMode: "monotone"
}
]
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: tooltipItem => {
const time = tooltipItem[0].xLabel.match(/(\d?\d):?(\d?\d?)/);
const h = parseInt(time[1], 10);
const m = parseInt(time[2], 10) || 0;
const from = padNumber(h) + ":" + padNumber(m) + ":00";
const to = padNumber(h) + ":" + padNumber(m + 9) + ":59";
return "Queries from " + from + " to " + to;
},
label: (tooltipItems, data) => {
if (tooltipItems.datasetIndex === 1) {
let percentage = 0.0;
const total = parseInt(data.datasets[0].data[tooltipItems.index], 10);
const blocked = parseInt(data.datasets[1].data[tooltipItems.index], 10);
if (total > 0)
percentage = 100.0 * blocked / total;
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel
+ " (" + percentage.toFixed(1) + "%)";
}
else
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel;
}
}
},
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "hour",
displayFormats: {
hour: "HH:mm"
},
tooltipFormat: "HH:mm"
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
maintainAspectRatio: false
}
};
constructor(props) {
super(props);
this.state = {
data: {
labels: [],
datasets: [
{
label: "Total Queries",
data: [],
fill: true,
backgroundColor: "rgba(220,220,220,0.5)",
borderColor: "rgba(0, 166, 90,.8)",
pointBorderColor: "rgba(0, 166, 90,.8)",
pointRadius: 1,
pointHoverRadius: 5,
pointHitRadius: 5,
cubicInterpolationMode: "monotone"
},
{
label: "Blocked Queries",
data: [],
fill: true,
backgroundColor: "rgba(0,192,239,0.5)",
borderColor: "rgba(0,192,239,1)",
pointBorderColor: "rgba(0,192,239,1)",
pointRadius: 1,
pointHoverRadius: 5,
pointHitRadius: 5,
cubicInterpolationMode: "monotone"
}
]
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: (tooltipItem, data) => {
const time = tooltipItem[0].xLabel.match(/(\d?\d):?(\d?\d?)/);
const h = parseInt(time[1], 10);
const m = parseInt(time[2], 10) || 0;
const from = padNumber(h) + ":" + padNumber(m) + ":00";
const to = padNumber(h) + ":" + padNumber(m + 9) + ":59";
return "Queries from " + from + " to " + to;
},
label: (tooltipItems, data) => {
if (tooltipItems.datasetIndex === 1) {
let percentage = 0.0;
const total = parseInt(data.datasets[0].data[tooltipItems.index], 10);
const blocked = parseInt(data.datasets[1].data[tooltipItems.index], 10);
if (total > 0)
percentage = 100.0 * blocked / total;
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel
+ " (" + percentage.toFixed(1) + "%)";
}
else
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel;
}
}
},
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "hour",
displayFormats: {
hour: "HH:mm"
},
tooltipFormat: "HH:mm"
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
maintainAspectRatio: false
}
};
this.updateGraph = this.updateGraph.bind(this);
}
@@ -118,9 +117,7 @@ export default class QueriesGraph extends Component {
data.datasets[0].data = res.domains_over_time[1];
data.datasets[1].data = res.ads_over_time[1];
this.setState({
data: data
});
this.setState({ data });
})
.catch(() => null);
}

View File

@@ -5,15 +5,13 @@ import 'react-table/react-table.css';
export default class QueryLog extends Component {
updateHandler = null;
state = {
history: [],
loading: true
};
constructor(props) {
super(props);
this.state = {
history: [],
loading: true
};
this.updateTable = this.updateTable.bind(this);
}

View File

@@ -3,77 +3,77 @@ import { Line } from 'react-chartjs-2';
import { padNumber, parseObjectForGraph, api, makeCancelable } from '../../utils';
export default class QueryTypesOverTime extends Component {
state = {
data: {
labels: [],
datasets: [
{
label: "A: IPv4 queries",
pointRadius: 0,
pointHitRadius: 5,
pointHoverRadius: 5,
backgroundColor: "#20a8d8",
data: []
},
{
label: "AAAA: IPv6 queries",
pointRadius: 0,
pointHitRadius: 5,
pointHoverRadius: 5,
backgroundColor: "#f86c6b",
data: []
}
]
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: (tooltipItem, data) => {
const label = tooltipItem[0].xLabel;
const time = label.match(/(\d?\d):?(\d?\d?)/);
const h = parseInt(time[1], 10);
const m = parseInt(time[2], 10) || 0;
const from = padNumber(h)+":"+padNumber(m-5)+":00";
const to = padNumber(h)+":"+padNumber(m+4)+":59";
return "Query types from "+from+" to "+to;
},
label: (tooltipItems, data) => {
return data.datasets[tooltipItems.datasetIndex].label + ": " + (100.0*tooltipItems.yLabel).toFixed(1) + "%";
}
}
},
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "hour",
displayFormats: {
hour: "HH:mm"
},
tooltipFormat: "HH:mm"
}
}],
yAxes: [{
ticks: {
mix: 0.0,
max: 1.0,
beginAtZero: true,
callback: (value, index, values) => Math.round(value*100) + "%"
},
stacked: true
}]
},
maintainAspectRatio: true
}
};
constructor(props) {
super(props);
this.state = {
data: {
labels: [],
datasets: [
{
label: "A: IPv4 queries",
pointRadius: 0,
pointHitRadius: 5,
pointHoverRadius: 5,
backgroundColor: "#20a8d8",
data: []
},
{
label: "AAAA: IPv6 queries",
pointRadius: 0,
pointHitRadius: 5,
pointHoverRadius: 5,
backgroundColor: "#f86c6b",
data: []
}
]
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: (tooltipItem, data) => {
const label = tooltipItem[0].xLabel;
const time = label.match(/(\d?\d):?(\d?\d?)/);
const h = parseInt(time[1], 10);
const m = parseInt(time[2], 10) || 0;
const from = padNumber(h)+":"+padNumber(m-5)+":00";
const to = padNumber(h)+":"+padNumber(m+4)+":59";
return "Query types from "+from+" to "+to;
},
label: (tooltipItems, data) => {
return data.datasets[tooltipItems.datasetIndex].label + ": " + (100.0*tooltipItems.yLabel).toFixed(1) + "%";
}
}
},
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "hour",
displayFormats: {
hour: "HH:mm"
},
tooltipFormat: "HH:mm"
}
}],
yAxes: [{
ticks: {
mix: 0.0,
max: 1.0,
beginAtZero: true,
callback: (value, index, values) => Math.round(value*100) + "%"
},
stacked: true
}]
},
maintainAspectRatio: true
}
};
this.updateGraph = this.updateGraph.bind(this);
}
@@ -118,9 +118,7 @@ export default class QueryTypesOverTime extends Component {
data.datasets[0].data = data_A;
data.datasets[1].data = data_AAAA;
this.setState({
data: data
});
this.setState({ data });
})
.catch(() => null);
}

View File

@@ -1,57 +1,54 @@
import React, { Component } from 'react';
import React from 'react';
import { NavLink } from 'react-router-dom'
import logo from '../../img/logo.svg';
export default class Sidebar extends Component {
handleClick(e) {
e.preventDefault();
e.target.parentElement.classList.toggle('open');
}
//const handleClick = (e) => {
// e.preventDefault();
// e.target.parentElement.classList.toggle('open');
//};
activeRoute(routeName) {
return this.props.location.pathname.indexOf(routeName) > -1 ? 'nav-item nav-dropdown open' : 'nav-item nav-dropdown';
}
//const activeRoute = (routeName) => {
// return this.props.location.pathname.indexOf(routeName) > -1 ? 'nav-item nav-dropdown open' : 'nav-item nav-dropdown';
//}
// secondLevelActive(routeName) {
// return this.props.location.pathname.indexOf(routeName) > -1 ? "nav nav-second-level collapse in" : "nav nav-second-level collapse";
// }
//const secondLevelActive = (routeName) => {
// return this.props.location.pathname.indexOf(routeName) > -1 ? "nav nav-second-level collapse in" : "nav nav-second-level collapse";
//}
render() {
return (
<div className="sidebar">
<nav className="sidebar-nav">
<ul className="nav">
<li className="nav-title">
<img src="/img/logo.svg" className="img-responsive pull-left" style={{height: "67px"}} alt=""/>
<p className="pull-left"
style={{
paddingLeft: "15px", textTransform: "initial", fontSize: "14px", marginBottom: "initial",
lineHeight: "14px", color: "white"
}}>
Pi-hole
</p>
<br/>
<span style={{textTransform: "initial", paddingLeft: "15px"}}>
<i className="fa fa-circle text-success"/> Online
</span>
</li>
<li className="nav-item">
<NavLink to={'/dashboard'} className="nav-link" activeClassName="active">
<i className="fa fa-dashboard"/> Dashboard
</NavLink>
</li>
<li className="nav-item">
<NavLink to={'/query-log'} className="nav-link" activeClassName="active">
<i className="fa fa-database"/> Query Log
</NavLink>
</li>
<li className="nav-item">
<NavLink to={'/whitelist'} className="nav-link" activeClassName="active">
<i className="fa fa-check-square-o"/> Whitelist
</NavLink>
</li>
</ul>
</nav>
</div>
)
}
}
export default () => (
<div className="sidebar">
<nav className="sidebar-nav">
<ul className="nav">
<li className="nav-title">
<img src={logo} className="img-responsive pull-left" style={{height: "67px"}} alt=""/>
<p className="pull-left"
style={{
paddingLeft: "15px", textTransform: "initial", fontSize: "14px", marginBottom: "initial",
lineHeight: "14px", color: "white"
}}>
Pi-hole
</p>
<br/>
<span style={{textTransform: "initial", paddingLeft: "15px"}}>
<i className="fa fa-circle text-success"/> Online
</span>
</li>
<li className="nav-item">
<NavLink to={'/dashboard'} className="nav-link" activeClassName="active">
<i className="fa fa-dashboard"/> Dashboard
</NavLink>
</li>
<li className="nav-item">
<NavLink to={'/query-log'} className="nav-link" activeClassName="active">
<i className="fa fa-database"/> Query Log
</NavLink>
</li>
<li className="nav-item">
<NavLink to={'/whitelist'} className="nav-link" activeClassName="active">
<i className="fa fa-check-square-o"/> Whitelist
</NavLink>
</li>
</ul>
</nav>
</div>
);

View File

@@ -2,16 +2,16 @@ import React, { Component } from 'react';
import { api, makeCancelable } from '../../utils';
export default class SummaryStats extends Component {
state = {
blockedQueries: "---",
totalQueries: "---",
percentBlocked: "---",
gravityDomains: "---",
uniqueClients: "---"
};
constructor(props) {
super(props);
this.state = {
blockedQueries: "---",
totalQueries: "---",
percentBlocked: "---",
gravityDomains: "---",
uniqueClients: "---"
};
this.updateStats = this.updateStats.bind(this);
}

View File

@@ -2,14 +2,13 @@ import React, { Component } from 'react';
import { api, makeCancelable } from '../../utils';
export default class TopBlocked extends Component {
state = {
total_blocked: 0,
top_blocked: {}
};
constructor(props) {
super(props);
this.state = {
total_blocked: 0,
top_blocked: {}
};
this.updateChart = this.updateChart.bind(this);
}
@@ -48,7 +47,7 @@ export default class TopBlocked extends Component {
<th>Frequency</th>
</tr>
{
Object.keys(this.state.top_blocked).map((item, index) => {
Object.keys(this.state.top_blocked).map(item => {
const stat = this.state.top_blocked[item];
const percentage = stat / this.state.total_blocked * 100;
return (

View File

@@ -2,14 +2,13 @@ import React, { Component } from 'react';
import { api, makeCancelable } from '../../utils';
export default class TopClients extends Component {
state = {
total_queries: 0,
top_clients: {}
};
constructor(props) {
super(props);
this.state = {
total_queries: 0,
top_clients: {}
};
this.updateChart = this.updateChart.bind(this);
}
@@ -48,7 +47,7 @@ export default class TopClients extends Component {
<th>Frequency</th>
</tr>
{
Object.keys(this.state.top_clients).map((item, index) => {
Object.keys(this.state.top_clients).map((item) => {
let hostname = "";
let ipAddr = "";
const stat = this.state.top_clients[item];

View File

@@ -2,14 +2,13 @@ import React, { Component } from 'react';
import { api, makeCancelable } from '../../utils';
export default class TopDomains extends Component {
state = {
total_queries: 0,
top_domains: {}
};
constructor(props) {
super(props);
this.state = {
total_queries: 0,
top_domains: {}
};
this.updateChart = this.updateChart.bind(this);
}
@@ -48,7 +47,7 @@ export default class TopDomains extends Component {
<th>Frequency</th>
</tr>
{
Object.keys(this.state.top_domains).map((item, index) => {
Object.keys(this.state.top_domains).map(item => {
const stat = this.state.top_domains[item];
const percentage = stat / this.state.total_queries * 100;
return (

View File

@@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { Switch, Route, Redirect } from 'react-router-dom'
import Header from '../../components/Header';
import Sidebar from '../../components/Sidebar';
@@ -9,28 +9,24 @@ import Dashboard from '../../views/Dashboard';
import QueryLog from '../../components/QueryLog';
import Whitelist from '../../views/Whitelist';
export default class Full extends Component {
render() {
return (
<div className="app">
<Header />
<div className="app-body">
<Sidebar {...this.props}/>
<main className="main">
<Breadcrumb />
<div className="container-fluid">
<Switch>
<Route path="/dashboard" name="Dashboard" component={Dashboard}/>
<Redirect exact from="/" to="/dashboard"/>
<Route path="/query-log" name="Query Log" component={QueryLog}/>
<Route path="/whitelist" name="Whitelist" component={Whitelist}/>
</Switch>
</div>
</main>
<Aside />
export default props => (
<div className="app">
<Header />
<div className="app-body">
<Sidebar {...props}/>
<main className="main">
<Breadcrumb />
<div className="container-fluid">
<Switch>
<Route path="/dashboard" name="Dashboard" component={Dashboard}/>
<Redirect exact from="/" to="/dashboard"/>
<Route path="/query-log" name="Query Log" component={QueryLog}/>
<Route path="/whitelist" name="Whitelist" component={Whitelist}/>
</Switch>
</div>
<Footer />
</div>
);
}
}
</main>
<Aside />
</div>
<Footer />
</div>
);

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import SummaryStats from './../../components/SummaryStats';
import QueriesGraph from './../../components/QueriesGraph';
import QueryTypesOverTime from './../../components/QueryTypesOverTime';
@@ -7,22 +7,18 @@ import TopDomains from './../../components/TopDomains';
import TopBlocked from './../../components/TopBlocked';
import TopClients from './../../components/TopClients';
export default class Dashboard extends Component {
render() {
return (
<div className="animated fadeIn">
<SummaryStats/>
<QueriesGraph/>
<div className="row">
<QueryTypesOverTime/>
<ForwardDestOverTime/>
</div>
<div className="row">
<TopDomains/>
<TopBlocked/>
<TopClients/>
</div>
</div>
);
}
}
export default () => (
<div className="animated fadeIn">
<SummaryStats/>
<QueriesGraph/>
<div className="row">
<QueryTypesOverTime/>
<ForwardDestOverTime/>
</div>
<div className="row">
<TopDomains/>
<TopBlocked/>
<TopClients/>
</div>
</div>
);