1
Fork 0

Merge pull request #7 from RealOrangeOne/contact-page

Add basic contact page
This commit is contained in:
Jake Howard 2017-02-11 21:19:02 +00:00 committed by GitHub
commit 34cab118cf
11 changed files with 124 additions and 39 deletions

View file

@ -49,13 +49,13 @@ accounts:
- fa-trello
freenode:
- Freenode IRC
- Freenode
- TheOrangeOne
- https://webchat.freenode.net/
- fa-rss
atomio:
- AtomIO Slack
- Atom Slack
- TheOrangeOne
- https://atomio.slack.com/
- fa-slack
@ -69,14 +69,14 @@ accounts:
codepen:
- CodePen
- TheOrangeOne
- https://codepen.io/~{0}/
- https://codepen.io/{0}/
- fa-codepen
npm:
- npm
- TheOrangeOne
- https://www.npmjs.com/~{0}/
- fa-file-code-io
- fa-file-code-o
footer_accounts:
- github

View file

@ -1,6 +1,5 @@
<head>
<meta name="slug" content="about" />
<meta name="title" content="About" />
<meta name="title" content="About Me" />
<meta name="no_container" content="true" />
</head>
<body>
@ -14,36 +13,40 @@
</div>
<script async defer src="//cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
</section>
<section class="bg-primary" id="website">
<section class="bg-primary">
<div class="container">
<h2>Website</h2>
<h2 class="section-heading">Personal Data</h2>
<p>
My website is the culmination of all my knowledge, compiled into 1 place. It not only contains all my projects, but is itself is a project.
In the interest of privacy, there's very little personal information here.
</p>
<p>
The site is primarily built with <a href="http://getpelican.com">Pelican</a>, a static site generator. This allows me to write nice clean, <i>DRY</i> content, and have it come out as clean, minified HTML.
</p>
<p>
The Javascript is built using <a href="http://browserify.org/">Browserify</a>, and the CSS is built using <a href="https://github.com/sass/node-sass">node-SCSS</a>. Both are run as a build step when pelican builds.
The information that is here is eitther not personal enough to bother protecting, or has been selectively chosen as nothing bad.
</p>
</div>
</section>
<section id="server">
<section>
<div class="container">
<h2>Server</h2>
<h2 class="section-heading">Accounts</h2>
<p>
The website is hosted on part of my dedicated server from <a href="https://www.soyoustart.com/en/">SoYouStart</a>, running an Ubuntu Server VM with <a href="http://dokku.viewdocs.io/dokku/">Dokku</a> installed.
These are all the accounts I run, all to do with various things. Take a look!
</p>
<p>
The prebuilt static files are served using a <a href="https://github.com/RealOrangeOne/tstatic">custom Express server</a>, to make the site as fast and effective as possible.
</p>
</div>
</section>
<section class="text-center">
<div class="container">
<div class="btn-group">
<a class="btn btn-github btn-xl" href="https://github.com/RealOrangeOne/theorangeone.net"><i class="fa fa-github fa-lg"></i> View Source</a>
<div class="row text-center">
{% for key, account in ACCOUNTS.items() %}
<div class="col-sm-3 col-xs-6">
<div class="service-box account">
<a href="{{ account.url }}" class="no-underline">
<i class="fa fa-4x {{ account.icon }}"></i>
<h3>{{ account.site }}</h3>
</a>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<section class="bg-primary text-center">
<div class="container">
<a class="btn btn-primary-dark btn-xl" href="/contact/">Contact Me</a>
</div>
</section>
</body>

View file

@ -0,0 +1,27 @@
<head>
<meta name="title" content="Contact Me" />
<meta name="no_container" content="true" />
</head>
<body>
<section>
<div class="container">
<p>
The fastest way to contact me is through twitter. Just tag me or send me a message and I'll respond as soon as possible!
</p>
</div>
</section>
<section class="bg-primary">
<div class="container">
<h2 class="section-heading">Need something more formal?</h2>
<p>
If you need to contact me in a more formal capacity, send me an email! I aim to respond to all emails within 3 days.
</p>
</div>
</section>
<section class="text-center">
<div class="container">
<a class="btn btn-primary btn-xl margin protected-mailto" data-value="{{ CONTACT_EMAIL|encode_text }}">Send me an email!</a>
<a class="btn btn-primary btn-xl margin" href="{{ ACCOUNTS.twitter.url }}">View Twitter</a>
</div>
</section>
</body>

View file

@ -7,6 +7,7 @@ sys.path.insert(0, os.path.realpath('./'))
AUTHOR = "Jake Howard"
SITENAME = "TheOrangeOne"
SITEURL = "https://theorangeone.net"
CONTACT_EMAIL = "info@theorangeone.net"
PATH = 'content'
TIMEZONE = "Europe/London"
DEFAULT_LANG = "en"
@ -111,7 +112,8 @@ JINJA_FILTERS = {
"limit": filters.limit,
"get_title": filters.get_title,
"get_html_title": filters.get_html_title,
"get_image": filters.get_image
"get_image": filters.get_image,
"encode_text": filters.encode_text
}
JINJA_ENVIRONMENT = {

View file

@ -39,3 +39,7 @@ def get_html_title(instance):
def get_image(instance):
return get_attribute(instance, 'image') or (hasattr(instance, 'page') and get_attribute(instance.page, 'name')) or ''
def encode_text(text):
return " ".join([str(ord(c)) for c in text])

View file

@ -9,7 +9,7 @@ class TestClient:
def get(self, path, JS=True):
file_path = self.build_path(path)
content = "".join(open(file_path).readlines())
if path.endswith('html'):
if file_path.endswith('html'):
content = BeautifulSoup(content, 'html.parser')
if JS:
for script in content(["noscript"]): # Remove noscript tags
@ -19,6 +19,8 @@ class TestClient:
def build_path(self, path):
if path.startswith('/'):
path = path[1:]
if path.endswith('/'):
path += 'index.html'
return os.path.join(self.output_path, path)
def exists(self, path):

View file

@ -96,5 +96,11 @@ class TestClientTestCase(TestCase):
def test_file_exists(self):
self.assertTrue(self.client.exists('index.html'))
def test_build_path_without_index(self):
self.assertEqual(
self.client.build_path('foo/'),
self.client.build_path('foo/index.html')
)
def test_file_doesnt_exist(self):
self.assertFalse(self.client.exists('foo.bar'))

View file

@ -1,5 +1,6 @@
from tests import TestCase
from config import social as social_settings
import pelicanconf as settings
import os.path
@ -47,18 +48,6 @@ class AboutPageTestCase(TestCase):
self.assertHeaderTitle(content, 'About')
self.assertTitle(content, 'About')
def test_website_section(self):
content = self.client.get('about/index.html')
section = content.find('section', id='website')
subtitle = section.find('h2')
self.assertEqual('Website', self.get_children(subtitle))
def test_server_section(self):
content = self.client.get('about/index.html')
section = content.find('section', id='server')
subtitle = section.find('h2')
self.assertEqual('Server', self.get_children(subtitle))
def test_github_card(self):
content = self.client.get('about/index.html')
tags = content.find_all('div', class_='github-card')
@ -67,6 +56,33 @@ class AboutPageTestCase(TestCase):
self.assertEqual('medium', tag.attrs['data-theme'])
self.assertEqual(social_settings['accounts']['github'][1], tag.attrs['data-github'])
def test_accounts(self):
content = self.client.get('about/index.html')
accounts = content.find_all('div', class_='account')
defined_accounts = [s for k, s in settings.ACCOUNTS.items()]
self.assertEqual(len(accounts), len(defined_accounts))
site_names = [s['site'] for s in defined_accounts]
urls = [s['url'] for s in defined_accounts]
icons = [s['icon'] for s in defined_accounts]
for account in accounts:
self.assertIn(account.find('a').attrs['href'], urls)
self.assertIn(account.find('i').attrs['class'][-1], icons)
self.assertIn(self.get_children(account.find('h3')), site_names)
class ContactPageTestCase(TestCase):
def test_title(self):
content = self.client.get('contact/')
self.assertHeaderTitle(content, 'Contact Me')
self.assertTitle(content, 'Contact Me')
def test_contact_links(self):
content = self.client.get('contact/')
links = content.find_all('section')[2].find_all('a')
self.assertEqual(links[1].attrs['href'], settings.ACCOUNTS['twitter']['url'])
decoded_value = ''.join([chr(int(c)) for c in links[0].attrs['data-value'].split(' ')])
self.assertEqual(decoded_value, settings.CONTACT_EMAIL)
class Page404TestCase(TestCase):
def test_title(self):

View file

@ -30,3 +30,14 @@ $('.navbar-brand').bind('click', function (event) {
}
event.preventDefault();
});
$('.protected-mailto').bind('click', function (evt) {
evt.preventDefault();
var char_codes = $(this).data('value').split(' ');
var plain_text = [];
for (var i = 0; i < char_codes.length; i++) {
plain_text.push(String.fromCharCode(parseInt(char_codes[i], 10)));
}
window.location = 'mailto:' + plain_text.join('');
});

View file

@ -16,3 +16,7 @@
padding: 0 $grid-gutter-width / 2;
}
a.no-underline:hover {
text-decoration: inherit;
}

View file

@ -110,3 +110,13 @@ header#header {
.github-card-container > iframe {
max-width: 100%;
}
.protected-mailto {
cursor: pointer;
}
.service-box.account {
a:hover {
color: $brand-orange-dark;
}
}