+ client: login page
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
.footer {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.footer__row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -8,6 +12,12 @@
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.footer__column--links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer__column--language {
|
||||
min-width: 220px;
|
||||
margin-bottom: 0;
|
||||
@@ -16,7 +26,7 @@
|
||||
.footer__link {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 15px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.footer__link--report {
|
||||
@@ -42,4 +52,12 @@
|
||||
min-width: initial;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.footer__column--links {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer__link {
|
||||
margin: 0 20px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Trans, withNamespaces } from 'react-i18next';
|
||||
import { REPOSITORY, LANGUAGES, PRIVACY_POLICY_LINK } from '../../helpers/constants';
|
||||
import i18n from '../../i18n';
|
||||
|
||||
import Version from './Version';
|
||||
import './Footer.css';
|
||||
import './Select.css';
|
||||
|
||||
@@ -14,42 +16,98 @@ class Footer extends Component {
|
||||
|
||||
changeLanguage = (event) => {
|
||||
i18n.changeLanguage(event.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
dnsVersion, processingVersion, getVersion,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<footer className="footer">
|
||||
<div className="container">
|
||||
<div className="footer__row">
|
||||
<div className="footer__column">
|
||||
<div className="footer__copyright">
|
||||
<Trans>copyright</Trans> © {this.getYear()} <a href="https://adguard.com/">AdGuard</a>
|
||||
<Fragment>
|
||||
<footer className="footer">
|
||||
<div className="container">
|
||||
<div className="footer__row">
|
||||
{!dnsVersion && (
|
||||
<div className="footer__column">
|
||||
<div className="footer__copyright">
|
||||
<Trans>copyright</Trans> © {this.getYear()}{' '}
|
||||
<a href="https://adguard.com/">AdGuard</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="footer__column footer__column--links">
|
||||
<a
|
||||
href={REPOSITORY.URL}
|
||||
className="footer__link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Trans>homepage</Trans>
|
||||
</a>
|
||||
<a
|
||||
href={PRIVACY_POLICY_LINK}
|
||||
className="footer__link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Trans>privacy_policy</Trans>
|
||||
</a>
|
||||
<a
|
||||
href={REPOSITORY.ISSUES}
|
||||
className="btn btn-outline-primary btn-sm footer__link footer__link--report"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Trans>report_an_issue</Trans>
|
||||
</a>
|
||||
</div>
|
||||
<div className="footer__column footer__column--language">
|
||||
<select
|
||||
className="form-control select select--language"
|
||||
value={i18n.language}
|
||||
onChange={this.changeLanguage}
|
||||
>
|
||||
{LANGUAGES.map(language => (
|
||||
<option key={language.key} value={language.key}>
|
||||
{language.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer__column">
|
||||
<a href={REPOSITORY.URL} className="footer__link" target="_blank" rel="noopener noreferrer">
|
||||
<Trans>homepage</Trans>
|
||||
</a>
|
||||
<a href={PRIVACY_POLICY_LINK} className="footer__link" target="_blank" rel="noopener noreferrer">
|
||||
<Trans>privacy_policy</Trans>
|
||||
</a>
|
||||
<a href={REPOSITORY.ISSUES} className="btn btn-outline-primary btn-sm footer__link footer__link--report" target="_blank" rel="noopener noreferrer">
|
||||
<Trans>report_an_issue</Trans>
|
||||
</a>
|
||||
</div>
|
||||
<div className="footer__column footer__column--language">
|
||||
<select className="form-control select select--language" value={i18n.language} onChange={this.changeLanguage}>
|
||||
{LANGUAGES.map(language =>
|
||||
<option key={language.key} value={language.key}>
|
||||
{language.name}
|
||||
</option>)}
|
||||
</select>
|
||||
</div>
|
||||
</footer>
|
||||
{dnsVersion && (
|
||||
<div className="footer">
|
||||
<div className="container">
|
||||
<div className="footer__row">
|
||||
<div className="footer__column">
|
||||
<div className="footer__copyright">
|
||||
<Trans>copyright</Trans> © {this.getYear()}{' '}
|
||||
<a href="https://adguard.com/">AdGuard</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer__column footer__column--language">
|
||||
<Version
|
||||
dnsVersion={dnsVersion}
|
||||
processingVersion={processingVersion}
|
||||
getVersion={getVersion}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Footer.propTypes = {
|
||||
dnsVersion: PropTypes.string,
|
||||
processingVersion: PropTypes.bool,
|
||||
getVersion: PropTypes.func,
|
||||
};
|
||||
|
||||
export default withNamespaces()(Footer);
|
||||
|
||||
@@ -131,6 +131,10 @@ const Icons = () => (
|
||||
<symbol id="question" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2">
|
||||
<circle cx="12" cy="12" r="10" /><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" /><line x1="12" y1="17" x2="12" y2="17" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2">
|
||||
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line>
|
||||
</symbol>
|
||||
</svg>
|
||||
);
|
||||
|
||||
|
||||
@@ -4,7 +4,13 @@
|
||||
}
|
||||
|
||||
.page-title__actions {
|
||||
display: inline-block;
|
||||
vertical-align: baseline;
|
||||
margin-left: 20px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.page-title__actions {
|
||||
display: inline-block;
|
||||
vertical-align: baseline;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ section {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
|
||||
40
client/src/components/ui/Version.css
Normal file
40
client/src/components/ui/Version.css
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
.version {
|
||||
font-size: 0.80rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1280px) {
|
||||
.version {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
|
||||
.version__value {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 992px) {
|
||||
.version__value {
|
||||
max-width: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.version__link {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border-bottom: 1px dashed #495057;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.version__text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 992px) {
|
||||
.version__text {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
39
client/src/components/ui/Version.js
Normal file
39
client/src/components/ui/Version.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Trans, withNamespaces } from 'react-i18next';
|
||||
|
||||
import './Version.css';
|
||||
|
||||
const Version = (props) => {
|
||||
const {
|
||||
dnsVersion, processingVersion, t,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div className="version">
|
||||
<div className="version__text">
|
||||
<Trans>version</Trans>: <span className="version__value" title={dnsVersion}>{dnsVersion}</span>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-icon btn-icon-sm btn-outline-primary btn-sm ml-2"
|
||||
onClick={() => props.getVersion(true)}
|
||||
disabled={processingVersion}
|
||||
title={t('check_updates_now')}
|
||||
>
|
||||
<svg className="icons">
|
||||
<use xlinkHref="#refresh" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Version.propTypes = {
|
||||
dnsVersion: PropTypes.string.isRequired,
|
||||
getVersion: PropTypes.func.isRequired,
|
||||
processingVersion: PropTypes.bool.isRequired,
|
||||
t: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default withNamespaces()(Version);
|
||||
Reference in New Issue
Block a user