Start admin area, create dashboard

fix/tabs-bar-issues
Alex Gleason 2020-12-29 12:34:23 -06:00
rodzic 10c9a90701
commit d3daf63dd5
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
6 zmienionych plików z 186 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,22 @@
import React from 'react';
import Icon from 'soapbox/components/icon';
import { NavLink } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
export default
class AdminNav extends React.PureComponent {
render() {
return (
<div className='wtf-panel promo-panel'>
<div className='promo-panel__container'>
<NavLink className='promo-panel-item' to='/admin'>
<Icon id='tachometer' className='promo-panel-item__icon' fixedWidth />
<FormattedMessage id='admin_nav.dashboard' defaultMessage='Dashboard' />
</NavLink>
</div>
</div>
);
}
}

Wyświetl plik

@ -0,0 +1,78 @@
import React from 'react';
import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl';
import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Column from '../ui/components/column';
import { parseVersion } from 'soapbox/utils/features';
const messages = defineMessages({
heading: { id: 'column.admin.dashboard', defaultMessage: 'Dashboard' },
});
const mapStateToProps = (state, props) => ({
instance: state.get('instance'),
});
export default @connect(mapStateToProps)
@injectIntl
class Dashboard extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
instance: ImmutablePropTypes.map.isRequired,
};
render() {
const { intl, instance } = this.props;
const v = parseVersion(instance.get('version'));
return (
<Column icon='tachometer' heading={intl.formatMessage(messages.heading)} backBtnSlim>
<div className='dashcounters'>
<div className='dashcounter'>
<a href='/pleroma/admin/#/users/index'>
<div className='dashcounter__num'>
<FormattedNumber value={instance.getIn(['stats', 'user_count'])} />
</div>
<div className='dashcounter__label'>
<FormattedMessage id='admin.dashcounters.user_count_label' defaultMessage='users' />
</div>
</a>
</div>
<div className='dashcounter'>
<a href='/pleroma/admin/#/statuses/index'>
<div className='dashcounter__num'>
<FormattedNumber value={instance.getIn(['stats', 'status_count'])} />
</div>
<div className='dashcounter__label'>
<FormattedMessage id='admin.dashcounters.status_count_label' defaultMessage='posts' />
</div>
</a>
</div>
<div className='dashcounter'>
<div>
<div className='dashcounter__num'>
<FormattedNumber value={instance.getIn(['stats', 'domain_count'])} />
</div>
<div className='dashcounter__label'>
<FormattedMessage id='admin.dashcounters.domain_count_label' defaultMessage='known instances' />
</div>
</div>
</div>
</div>
<div className='dashwidgets'>
<div class='dashwidget'>
<h4><FormattedMessage id='admin.dashwidgets.software_header' defaultMessage='Software' /></h4>
<ul>
<li>Soapbox FE <span class='pull-right'>1.1.0</span></li>
<li>{v.software} <span class='pull-right'>{v.version}</span></li>
</ul>
</div>
</div>
</Column>
);
}
}

Wyświetl plik

@ -39,6 +39,7 @@ import Icon from 'soapbox/components/icon';
import { isStaff } from 'soapbox/utils/accounts';
import ChatPanes from 'soapbox/features/chats/components/chat_panes';
import ProfileHoverCard from 'soapbox/components/profile_hover_card';
import AdminNav from 'soapbox/features/admin/components/admin_nav';
import {
Status,
@ -86,6 +87,7 @@ import {
ChatIndex,
ChatRoom,
ServerInfo,
Dashboard,
} from './util/async-components';
// Dummy import, to make sure that <Status /> ends up in the application bundle.
@ -154,6 +156,14 @@ const LAYOUT = {
<FeaturesPanel key='0' />,
],
},
ADMIN: {
LEFT: [
<AdminNav key='0' />,
],
RIGHT: [
<LinkFooter key='1' />,
],
},
STATUS: {
TOP: null,
LEFT: null,
@ -274,6 +284,8 @@ class SwitchingColumnsArea extends React.PureComponent {
<WrappedRoute path='/settings/import' layout={LAYOUT.DEFAULT} component={ImportData} content={children} />
<WrappedRoute path='/soapbox/config' layout={LAYOUT.DEFAULT} component={SoapboxConfig} content={children} />
<Redirect from='/admin/dashboard' to='/admin' exact />
<WrappedRoute path='/admin' layout={LAYOUT.ADMIN} component={Dashboard} content={children} exact />
<WrappedRoute path='/info' layout={LAYOUT.EMPTY} component={ServerInfo} content={children} />
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />

Wyświetl plik

@ -217,3 +217,7 @@ export function ChatRoom() {
export function ServerInfo() {
return import(/* webpackChunkName: "features/server_info" */'../../server_info');
}
export function Dashboard() {
return import(/* webpackChunkName: "features/admin" */'../../admin');
}

Wyświetl plik

@ -79,6 +79,7 @@
@import 'components/snackbar';
@import 'components/accordion';
@import 'components/server-info';
@import 'components/admin';
// Holiday
@import 'holiday/halloween';

Wyświetl plik

@ -0,0 +1,69 @@
.dashcounters {
display: flex;
flex-wrap: wrap;
margin: 0 -5px 0;
padding: 20px;
}
.dashcounter {
box-sizing: border-box;
flex: 0 0 33.333%;
padding: 0 5px;
margin-bottom: 10px;
> a,
> div {
text-decoration: none;
color: inherit;
display: block;
padding: 20px;
background: var(--accent-color--faint);
border-radius: 4px;
transition: 0.2s;
}
> a:hover {
background: var(--accent-color--med);
transform: translateY(-2px);
}
&__num,
&__text {
text-align: center;
font-weight: 500;
font-size: 24px;
line-height: 30px;
color: var(--primary-text-color);
margin-bottom: 10px;
}
&__label {
font-size: 14px;
color: hsla(var(--primary-text-color_hsl), 0.6);
text-align: center;
font-weight: 500;
}
}
.dashwidgets {
display: flex;
flex-wrap: wrap;
margin: 0 -5px;
padding: 0 20px 20px 20px;
}
.dashwidget {
flex: 1;
margin-bottom: 20px;
padding: 0 5px;
h4 {
text-transform: uppercase;
font-size: 13px;
font-weight: 700;
color: #999;
padding-bottom: 8px;
margin-bottom: 8px;
border-bottom: 1px solid #cfeaf3;
}
}