commit
f02ced64ff
133 changed files with 2043 additions and 6358 deletions
6
.eslintrc
Normal file
6
.eslintrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "./node_modules/eslint-config/.eslintrc",
|
||||
"globals": {
|
||||
$: true
|
||||
}
|
||||
}
|
1
.nvmrc
Normal file
1
.nvmrc
Normal file
|
@ -0,0 +1 @@
|
|||
5.10.1
|
38
.spelling
Normal file
38
.spelling
Normal file
|
@ -0,0 +1,38 @@
|
|||
# markdown-spellcheck spelling configuration file
|
||||
# Format - lines beginning # are comments
|
||||
# global dictionary is at the start, file overrides afterwards
|
||||
# one word per line, to define a file override use ' - filename'
|
||||
# where filename is relative to this configuration file
|
||||
Django
|
||||
SQLite
|
||||
eg
|
||||
MyWindowsHosting
|
||||
nginx
|
||||
backends
|
||||
PyGame
|
||||
easter
|
||||
_Enabler
|
||||
Hipchat
|
||||
DabApps
|
||||
JakeSidSmith
|
||||
facepalm
|
||||
notsureif
|
||||
wat
|
||||
premis
|
||||
hipchat
|
||||
plugin
|
||||
firefox
|
||||
Jetpack
|
||||
Javascript
|
||||
facebook
|
||||
github
|
||||
morse
|
||||
wikipedia
|
||||
iframe
|
||||
querystring
|
||||
javascript
|
||||
jQuery
|
||||
gists
|
||||
Lenovo
|
||||
Collyer's
|
||||
til
|
22
LICENSE
22
LICENSE
|
@ -1,22 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Jake Howard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -1 +1,3 @@
|
|||
# My Website
|
||||
|
||||
[![Circle CI](https://circleci.com/gh/RealOrangeOne/theorangeone.net.svg?style=svg)](https://circleci.com/gh/RealOrangeOne/theorangeone.net)
|
||||
|
|
21
build
21
build
|
@ -1,11 +1,28 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ -z "$NVM_DIR" ]
|
||||
then
|
||||
NVM_DIR="$HOME/.nvm"
|
||||
fi
|
||||
|
||||
. $NVM_DIR/nvm.sh
|
||||
nvm install
|
||||
nvm use
|
||||
|
||||
set -e
|
||||
|
||||
pyvenv-3.4 env
|
||||
pyvenv env
|
||||
env/bin/pip install -r requirements.txt --upgrade
|
||||
|
||||
scripts/get-private-data.sh
|
||||
|
||||
npm install
|
||||
npm run build
|
||||
npm run build $@
|
||||
|
||||
env/bin/python manage.py collectstatic --noinput
|
||||
|
||||
if [[ $BUILD_PRODUCTION ]]
|
||||
then
|
||||
echo ">> Running Migrations..."
|
||||
env/bin/python manage.py migrate
|
||||
fi
|
||||
|
|
20
circle.yml
Normal file
20
circle.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
machine:
|
||||
python:
|
||||
version: 3.4.2
|
||||
node:
|
||||
version: 5.10.1
|
||||
environment:
|
||||
DEBUG: true
|
||||
DATABASE_URL: sqlite://~/database.db
|
||||
EMAIL_BACKEND: django.core.mail.backends.console.EmailBackend
|
||||
BUILD_PRODUCTION: true
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- ./build
|
||||
cache_directories:
|
||||
- env
|
||||
|
||||
test:
|
||||
override:
|
||||
- ./runtests
|
6
data/context.yml
Normal file
6
data/context.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
links:
|
||||
github: https://github.com/RealOrangeOne
|
||||
twitter: https://twitter.com/RealOrangeOne
|
||||
instagram: https://instagram.com/RealOrangeOne
|
||||
youtube: https://www.youtube.com/user/TheOrangeOneOfficial
|
||||
reddit: https://www.reddit.com/user/realorangeone
|
9
data/page_context.yml
Normal file
9
data/page_context.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
index:
|
||||
body_class: index
|
||||
html_title: Homepage
|
||||
|
||||
projects/hipchat-emoticons-for-all:
|
||||
header_image: https://hipchat-magnolia-cdn.atlassian.com/assets/img/hipchat/hipchat_og_image.jpg
|
||||
|
||||
projects/yoga-pal:
|
||||
header_image: http://www.lenovo.com/images/OneWebImages/SubSeries/gallery/laptops/IdeaPad-Yoga-13-Convertible-Laptop-PC-Clementine-Orange-Closed-Cover-View-gallery-940x529.jpg
|
1
data/path_switch.yml
Normal file
1
data/path_switch.yml
Normal file
|
@ -0,0 +1 @@
|
|||
college/attack-on-blocks: projects/attack-on-blocks
|
|
@ -1,3 +1,3 @@
|
|||
DEBUG=false
|
||||
DATABASE_URL=sqlite:///database.db
|
||||
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
|
||||
BUILD_PRODUCTION=true
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
DEBUG=true
|
||||
DATABASE_URL=sqlite:///database.db
|
||||
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
|
||||
|
|
61
package.json
61
package.json
|
@ -1,43 +1,50 @@
|
|||
{
|
||||
"name": "TheOrangeOne-Site",
|
||||
"version": "0.0.1",
|
||||
"description": "TheOrangeOne.net site",
|
||||
"main": "app.js",
|
||||
"version": "3.0.0",
|
||||
"description": " Source code for TheOrangeOne.net",
|
||||
"scripts": {
|
||||
"lint": "echo 'Nothing yet.';",
|
||||
"build-js": "bash scripts/build-js.sh",
|
||||
"create-build-dirs": "mkdir -p static/build/js static/build/fonts static/build/css static/build/img private",
|
||||
"lint": "eslint 'static/src/js/'",
|
||||
"build-js": "./scripts/build-js.sh",
|
||||
"create-build-dirs": "mkdir -p static/build/js/lib static/build/fonts static/build/css static/build/img",
|
||||
"build": "npm run create-build-dirs && npm run build-fonts && npm run build-images && npm run build-js && npm run build-less",
|
||||
"build-less": "lessc --silent static/src/less/style.less static/build/css/style.css && cleancss -d --s0 -o static/build/css/style.css static/build/css/style.css",
|
||||
"build-fonts": "cp -R node_modules/bootstrap/dist/fonts static/build/ && cp -R node_modules/ionicons-pre/fonts static/build/ ",
|
||||
"build-less": "./scripts/build-less.sh",
|
||||
"build-fonts": "cp -R node_modules/bootstrap/dist/fonts static/build/ && cp -R node_modules/ionicons/fonts static/build/ ",
|
||||
"build-images": "cp -r static/src/img/* static/build/img/",
|
||||
"watch-images": "watch 'npm run build-images' static/src/img/",
|
||||
"watch-less": "watch 'npm run build-less' static/src/less/",
|
||||
"watch": "npm run watch-less & npm run watch-images",
|
||||
"clean": "rm -rf static/build collected-static/ node_modules/ env/ private"
|
||||
"watch": "npm run watch-less",
|
||||
"clean": "./scripts/clean.js",
|
||||
"test": "npm run lint",
|
||||
"spellcheck": "mdspell --en-gb -ranx \"templates/**/*.*\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/RealOrangeOne/theorangeone.net"
|
||||
},
|
||||
"dependencies": {
|
||||
"bootstrap": "^3.3.5",
|
||||
"jquery": "^2.1.4",
|
||||
"less": "^2.5.1",
|
||||
"markdown": "^0.5.0",
|
||||
"react": "^0.13.3",
|
||||
"react-bootstrap": "^0.25.1",
|
||||
"skrollr": "^0.6.26"
|
||||
"animate.css": "=3.4.0",
|
||||
"bootstrap": "=3.3.5",
|
||||
"ionicons": "=2.0.1",
|
||||
"jquery": "=2.1.4",
|
||||
"react": "=0.13.3",
|
||||
"react-bootstrap": "=0.25.1",
|
||||
"whatwg-fetch": "=0.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^11.0.1",
|
||||
"clean-css": "^3.4.1",
|
||||
"eslint": "^1.5.0",
|
||||
"eslint-plugin-react": "^3.4.2",
|
||||
"ionicons-pre": "^1.0.0-pre",
|
||||
"react-tools": "^0.13.2",
|
||||
"reactify": "^1.1.1",
|
||||
"uglify-js": "^2.4.24",
|
||||
"watch": "^0.16.0"
|
||||
"autoprefixer": "=6.3.3",
|
||||
"babel-preset-es2015": "=6.1.18",
|
||||
"babel-preset-react": "=6.1.18",
|
||||
"babelify": "=7.2.0",
|
||||
"browserify": "=11.0.1",
|
||||
"clean-css": "=3.4.1",
|
||||
"eslint": "=1.5.0",
|
||||
"eslint-config": "git://github.com/dabapps/eslint-config.git",
|
||||
"eslint-plugin-react": "=3.4.2",
|
||||
"less": "=2.5.1",
|
||||
"less-mixins": "git://github.com/RealOrangeOne/less-mixins.git",
|
||||
"markdown-spellcheck": "=0.10.0",
|
||||
"postcss-cli": "=2.5.1",
|
||||
"react-tools": "=0.13.2",
|
||||
"uglify-js": "=2.4.24",
|
||||
"watch": "=0.16.0"
|
||||
}
|
||||
}
|
||||
|
|
67
project/blog/tests.py
Normal file
67
project/blog/tests.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
from django.test import TestCase
|
||||
import requests_mock, json
|
||||
from . import utils
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
|
||||
@requests_mock.mock()
|
||||
class WordPressAPITestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.test_blog_data = {
|
||||
"title": "Test Blog Post",
|
||||
"ID": 1,
|
||||
"content": "<p>Test blog post content</p>",
|
||||
"slug": "test-post"
|
||||
}
|
||||
self.invalid_blog_data = {
|
||||
"title": "Invalid blog post",
|
||||
"content": "<p></p>",
|
||||
"slug": "invalid"
|
||||
}
|
||||
|
||||
def test_gets_correct_data(self, m):
|
||||
payload = json.dumps(self.test_blog_data)
|
||||
m.get(utils.build_url(self.test_blog_data['slug']), text=payload)
|
||||
blog_data = utils.get_post(self.test_blog_data['slug'])
|
||||
self.assertEqual(blog_data, self.test_blog_data)
|
||||
|
||||
def test_invalid_response(self, m):
|
||||
payload = json.dumps(self.invalid_blog_data)
|
||||
m.get(utils.build_url(self.invalid_blog_data['slug']), text=payload)
|
||||
blog_data = utils.get_post(self.invalid_blog_data['slug'])
|
||||
self.assertFalse(blog_data)
|
||||
|
||||
def test_invalid_status(self, m):
|
||||
payload = json.dumps(self.test_blog_data)
|
||||
m.get(utils.build_url(self.test_blog_data['slug']), text=payload, status_code=500)
|
||||
blog_data = utils.get_post(self.test_blog_data['slug'])
|
||||
self.assertFalse(blog_data)
|
||||
|
||||
def test_no_slug(self, m):
|
||||
blog_data = utils.get_post('')
|
||||
self.assertFalse(blog_data)
|
||||
|
||||
|
||||
@requests_mock.mock()
|
||||
class BlogViewTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.test_blog_data = {
|
||||
"title": "Test Blog Post",
|
||||
"ID": 1,
|
||||
"content": "<p>Test blog post content</p>",
|
||||
"slug": "test-post",
|
||||
"date": "2000-01-01T18:05:00+00:00"
|
||||
}
|
||||
|
||||
def test_accessable(self, m):
|
||||
payload = json.dumps(self.test_blog_data)
|
||||
m.get(utils.build_url(self.test_blog_data['slug']), text=payload)
|
||||
response = self.client.get(reverse('blog:blog-post', args=[self.test_blog_data['slug']]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_correct_content(self, m):
|
||||
payload = json.dumps(self.test_blog_data)
|
||||
m.get(utils.build_url(self.test_blog_data['slug']), text=payload)
|
||||
response = self.client.get(reverse('blog:blog-post', args=[self.test_blog_data['slug']]))
|
||||
self.assertContains(response, self.test_blog_data['content'])
|
||||
self.assertEqual(response.context['html_title'], self.test_blog_data['title'])
|
6
project/blog/urls.py
Normal file
6
project/blog/urls.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.conf.urls import url
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^(?P<slug>.+)/?$', views.BlogView.as_view(), name='blog-post'),
|
||||
]
|
25
project/blog/utils.py
Normal file
25
project/blog/utils.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
import requests, iso8601
|
||||
from django.conf import settings
|
||||
|
||||
API_PATH = "https://public-api.wordpress.com/rest/v1.1/sites/{0}/posts/slug:{1}"
|
||||
|
||||
|
||||
def build_url(slug):
|
||||
if not slug:
|
||||
return
|
||||
return API_PATH.format(settings.WORDPRESS_URL, slug)
|
||||
|
||||
|
||||
def get_post(slug):
|
||||
if not slug:
|
||||
return
|
||||
response = requests.get(build_url(slug))
|
||||
|
||||
if response.status_code != 200:
|
||||
return
|
||||
data = response.json()
|
||||
return data if "ID" in data else False
|
||||
|
||||
|
||||
def reformat_date(iso_date):
|
||||
return iso8601.parse_date(iso_date).strftime("%x %I:%M")
|
22
project/blog/views.py
Normal file
22
project/blog/views.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from django.views.generic import TemplateView
|
||||
from .utils import get_post, reformat_date
|
||||
from django.http import Http404
|
||||
|
||||
|
||||
class BlogView(TemplateView):
|
||||
template_name = "blog/post.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['blog'] = self.blog_data
|
||||
context['blog']['date'] = reformat_date(self.blog_data['date'])
|
||||
context['html_title'] = self.blog_data['title']
|
||||
if 'featured_image' in self.blog_data:
|
||||
context['header_image'] = self.blog_data['featured_image']
|
||||
return context
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.blog_data = get_post(kwargs['slug'])
|
||||
if not self.blog_data:
|
||||
raise Http404
|
||||
return super().dispatch(request, *args, **kwargs)
|
|
@ -1,3 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
|
@ -1,3 +0,0 @@
|
|||
from django.db import models
|
||||
|
||||
# Create your models here.
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,7 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from .views import StudentServerView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^student-server', StudentServerView.as_view(), name='student-server')
|
||||
]
|
|
@ -1,5 +0,0 @@
|
|||
from django.views.generic import TemplateView
|
||||
from project.common.views import CustomHeaderBG
|
||||
|
||||
class StudentServerView(CustomHeaderBG.Template):
|
||||
template_name = 'college/student-server.html'
|
46
project/common/data.py
Normal file
46
project/common/data.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
import os.path
|
||||
import yaml
|
||||
from glob import glob
|
||||
from project.pages.utils import get_title_from_markdown, parse_content
|
||||
|
||||
|
||||
def get_data_from_file(base_dir, filename):
|
||||
with open(os.path.join(base_dir, 'data', filename)) as data_file:
|
||||
return yaml.load(data_file) or {}
|
||||
|
||||
|
||||
def generate_config(base_dir):
|
||||
default = get_data_from_file(base_dir, 'context.yml')
|
||||
page = get_data_from_file(base_dir, 'page_context.yml')
|
||||
switcher = get_data_from_file(base_dir, 'path_switch.yml')
|
||||
|
||||
# Add projects config
|
||||
default['projects'] = generate_projects(base_dir)
|
||||
# Join projects config with it's page context
|
||||
for i in range(len(default['projects'])):
|
||||
project = default['projects'][i]
|
||||
if project['path'] in page: # If there's a custom config
|
||||
default['projects'][i] = dict(project, **page[project['path']])
|
||||
|
||||
return default, page, switcher
|
||||
|
||||
|
||||
def generate_projects(base_dir):
|
||||
projects_path = os.path.join(base_dir, 'templates/projects')
|
||||
files = []
|
||||
for path in glob(projects_path + '/*.*'):
|
||||
filename = path.replace(projects_path, '')
|
||||
if filename == '/index.html':
|
||||
continue
|
||||
with open(path) as f:
|
||||
if filename.split('.')[1] == 'md':
|
||||
parsed_content = parse_content(f.read(), filename.split('.')[1])
|
||||
filename = get_title_from_markdown(parsed_content)
|
||||
else:
|
||||
filename = filename.split('.')[0]
|
||||
files.append({
|
||||
"name": filename,
|
||||
"path": 'projects' + path.replace(projects_path, '').split('.')[0],
|
||||
"url": '/projects' + path.replace(projects_path, '').split('.')[0],
|
||||
})
|
||||
return files
|
|
@ -1,3 +0,0 @@
|
|||
from django.db import models
|
||||
|
||||
# Create your models here.
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,13 +0,0 @@
|
|||
from django.views.generic import TemplateView
|
||||
|
||||
|
||||
class CustomHeaderBG():
|
||||
"""Allow custom header background"""
|
||||
|
||||
class Template(TemplateView):
|
||||
header_BG = ""
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['header_BG'] = self.header_BG
|
||||
return context
|
|
@ -1,3 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,8 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from .views import GalleryView, YoutubeView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^gallery', GalleryView.as_view(), name='gallery'),
|
||||
url(r'^youtube', YoutubeView.as_view(), name='youtube')
|
||||
]
|
|
@ -1,10 +0,0 @@
|
|||
from django.views.generic import TemplateView
|
||||
from project.common.views import CustomHeaderBG
|
||||
|
||||
|
||||
class YoutubeView(CustomHeaderBG.Template):
|
||||
template_name = "media/youtube.html"
|
||||
|
||||
|
||||
class GalleryView(TemplateView):
|
||||
template_name = "media/gallery.html"
|
|
@ -1,3 +1,19 @@
|
|||
# from django.test import TestCase
|
||||
from django.test import TestCase
|
||||
from django.conf import settings
|
||||
import os.path
|
||||
from glob import glob
|
||||
|
||||
# Create your tests here.
|
||||
|
||||
class PagesTestCase(TestCase):
|
||||
def setUp(self):
|
||||
directories = glob(os.path.join(settings.BASE_DIR, 'templates') + '/**/*.*')
|
||||
self.urls = []
|
||||
for directory in directories:
|
||||
if 'email' in directory or 'blog' in directory:
|
||||
continue
|
||||
self.urls.append(directory.replace(os.path.join(settings.BASE_DIR, 'templates'), '').split('.')[0].replace('index', ''))
|
||||
|
||||
def test_pages_accessable(self):
|
||||
for path in self.urls:
|
||||
response = self.client.get(path)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
from django.conf.urls import url
|
||||
from . import views
|
||||
from .views import page_view
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^about/website/$', views.AboutWebsiteView.as_view(), name='about-website'),
|
||||
url(r'^about/$', views.AboutIndexView.as_view(), name='about'),
|
||||
url(r'^no-js/$', views.NoJavascriptView.as_view(), name='no-js'),
|
||||
url(r'^404/$', views.Custom404View.as_view(), name='404'),
|
||||
url(r'^$', views.IndexView.as_view(), name='index')
|
||||
url(r'^(?P<path>.*)', page_view, name='page'),
|
||||
]
|
||||
|
|
29
project/pages/utils.py
Normal file
29
project/pages/utils.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
from django.conf import settings
|
||||
from bs4 import BeautifulSoup
|
||||
import markdown2
|
||||
|
||||
|
||||
def get_context(path):
|
||||
if path in settings.PAGE_CONTEXT:
|
||||
context = dict(settings.DEFAULT_CONTEXT, **settings.PAGE_CONTEXT[path])
|
||||
else:
|
||||
context = dict(settings.DEFAULT_CONTEXT)
|
||||
return context
|
||||
|
||||
|
||||
def get_title_from_markdown(md):
|
||||
html_tree = BeautifulSoup(md, "html.parser")
|
||||
tag = html_tree.find('h1')
|
||||
return tag.contents[0]
|
||||
|
||||
|
||||
def parse_content(content, extension):
|
||||
if extension == 'md':
|
||||
return markdown2.markdown(content)
|
||||
return content
|
||||
|
||||
|
||||
def swap_page(path):
|
||||
if path in settings.PAGE_SWITCH:
|
||||
return settings.PAGE_SWITCH[path]
|
||||
return path
|
|
@ -1,34 +1,33 @@
|
|||
from django.views.generic import TemplateView
|
||||
from project.common.views import CustomHeaderBG
|
||||
from django.contrib.staticfiles.templatetags.staticfiles import static
|
||||
import os.path
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.template.loader import get_template
|
||||
from .utils import get_context, parse_content, get_title_from_markdown, swap_page
|
||||
|
||||
|
||||
class IndexView(TemplateView):
|
||||
template_name = 'index.html'
|
||||
def page_view(request, path):
|
||||
template = None
|
||||
if path.endswith('/'): # Strip trailing slash
|
||||
path = path[:-1]
|
||||
|
||||
path = swap_page(path)
|
||||
|
||||
class NoJavascriptView(TemplateView):
|
||||
template_name = 'core/no-js.html'
|
||||
|
||||
|
||||
class Custom404View(CustomHeaderBG.Template):
|
||||
template_name = 'core/404.html'
|
||||
header_BG = static('img/ninjas.png')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['no_footer'] = True
|
||||
return context
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
context = self.get_context_data(**kwargs)
|
||||
return self.render_to_response(context, status=404)
|
||||
|
||||
|
||||
class AboutWebsiteView(CustomHeaderBG.Template):
|
||||
template_name = 'about/website.html'
|
||||
header_BG = ''
|
||||
|
||||
|
||||
class AboutIndexView(TemplateView):
|
||||
template_name = 'about/index.html'
|
||||
if os.path.isdir(os.path.join(settings.BASE_DIR, 'templates', path)):
|
||||
path = os.path.join(path, 'index')
|
||||
for extension in ['md', 'html']:
|
||||
try:
|
||||
template = get_template("{}.{}".format(path, extension))
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if not template:
|
||||
raise Http404
|
||||
context = get_context(path)
|
||||
parsed_content = parse_content(template.render(context, request), extension)
|
||||
if extension == 'md':
|
||||
template = get_template('markdown_content.html')
|
||||
context['markdown_content'] = parsed_content
|
||||
context['page_title'] = get_title_from_markdown(parsed_content)
|
||||
context['html_title'] = context['page_title']
|
||||
parsed_content = template.render(context, request)
|
||||
return HttpResponse(parsed_content)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,16 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
# Project URLs
|
||||
url(r'^attack-on-blocks', views.AttackOnBlocksView.as_view(), name="attack-on-blocks"),
|
||||
url(r'^bsod-enabler', views.BSODEnablerView.as_view(), name='bsod-enabler'),
|
||||
url(r'^hipchat-emoticons-for-all', views.HipChatEmoticonsForAllView.as_view(), name='hipchat-emoticons'),
|
||||
url(r'^pithos', views.PithosView.as_view(), name='pithos'),
|
||||
|
||||
# Code URLs
|
||||
url(r'^morse-code-decoder', views.MorseCodeDecoderView.as_view(), name='morse-code-decoder'),
|
||||
url(r'^wiki-game-solver', views.WikiGameSolverView.as_view(), name='wiki-game-solver'),
|
||||
|
||||
url(r'^', views.AllProjectsView.as_view(), name="index")
|
||||
]
|
|
@ -1,35 +0,0 @@
|
|||
from django.views.generic import TemplateView
|
||||
from project.common.views import CustomHeaderBG
|
||||
|
||||
|
||||
# Project Views
|
||||
class AllProjectsView(TemplateView):
|
||||
template_name = "projects/all_projects.html"
|
||||
|
||||
|
||||
class AttackOnBlocksView(CustomHeaderBG.Template):
|
||||
template_name = "college/attack-on-blocks.html"
|
||||
|
||||
|
||||
class BSODEnablerView(CustomHeaderBG.Template):
|
||||
template_name = 'projects/BSOD-Enabler.html'
|
||||
header_BG = 'http://cdn9.howtogeek.com/wp-content/uploads/2013/05/xwindows-8-blue-screen-error.png.pagespeed.ic.yOWUS_rYGn.png'
|
||||
|
||||
|
||||
class HipChatEmoticonsForAllView(CustomHeaderBG.Template):
|
||||
template_name = 'projects/hipchat-emoticons-for-all.html'
|
||||
header_BG = "https://info.seibert-media.net/plugins/servlet/pptslide?attachment=HipChat+Server+Sales+Pitch+Final+PPT.pptx&attachmentId=7536966&attachmentVer=1&pageId=3179011&slide=0"
|
||||
|
||||
|
||||
class PithosView(CustomHeaderBG.Template):
|
||||
template_name = 'projects/pithos.html'
|
||||
|
||||
|
||||
# Code Views
|
||||
class MorseCodeDecoderView(CustomHeaderBG.Template):
|
||||
template_name = 'projects/morse-code-decoder.html'
|
||||
|
||||
|
||||
class WikiGameSolverView(CustomHeaderBG.Template):
|
||||
template_name = 'projects/wiki-game-solver.html'
|
||||
header_BG = "http://is1.mzstatic.com/image/pf/us/r30/Purple/v4/a3/3f/31/a33f31dd-3ace-ffe4-5531-89d3f3a1106f/mzl.ihqwkbih.png"
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,10 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from .views import Index2015View, Index2014View, RoboticsIndexView, Robot2015View
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', RoboticsIndexView.as_view(), name='index' ),
|
||||
url(r'^2015', Index2015View.as_view(), name='2015-index'),
|
||||
url(r'^2015/robot', Robot2015View.as_view(), name='2015-robot'),
|
||||
url(r'^2014', Index2014View.as_view(), name='2014-index')
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
from django.views.generic import TemplateView
|
||||
from project.common.views import CustomHeaderBG
|
||||
|
||||
|
||||
class RoboticsIndexView(TemplateView):
|
||||
template_name = 'robotics/index.html'
|
||||
|
||||
# 2015
|
||||
class Index2015View(CustomHeaderBG.Template):
|
||||
template_name = 'robotics/2015-index.html'
|
||||
header_BG = "https://farm8.staticflickr.com/7711/17122633430_7d1bde923a_k.jpg"
|
||||
|
||||
|
||||
class Robot2015View(CustomHeaderBG.Template):
|
||||
template_name = 'robotics/2015-robot.html'
|
||||
header_BG = ""
|
||||
|
||||
|
||||
# 2014
|
||||
class Index2014View(CustomHeaderBG.Template):
|
||||
template_name = 'robotics/2014-index.html'
|
||||
header_BG = "nothing"
|
|
@ -1,19 +1,6 @@
|
|||
"""
|
||||
Django settings for project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.8.3.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||
"""
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import dj_database_url
|
||||
# import logging
|
||||
import os
|
||||
import sys
|
||||
import dj_database_url, os
|
||||
from private import export
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
@ -22,7 +9,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'q&^k#n_lkd5l9&g^k7$q1rhj_=%9yqy-)ln78ik414-bcowedy'
|
||||
SECRET_KEY = export('SECRET_KEY')
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
@ -31,23 +18,13 @@ ALLOWED_HOSTS = ['too.ctf.sh', 'theorangeone.net']
|
|||
|
||||
# Application definition
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
|
||||
'rest_framework',
|
||||
'bootstrapform',
|
||||
|
||||
'project.pages',
|
||||
'project.common',
|
||||
'project.projects',
|
||||
'project.robotics',
|
||||
'project.setup',
|
||||
'project.media',
|
||||
'project.college'
|
||||
'project.blog'
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
|
@ -85,7 +62,7 @@ WSGI_APPLICATION = 'project.wsgi.application'
|
|||
# Database
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||
DATABASES = {
|
||||
'default': dj_database_url.config(default=os.environ['DATABASE_URL'])
|
||||
'default': dj_database_url.config(default='sqlite://memory')
|
||||
}
|
||||
|
||||
EMAIL_BACKEND = os.environ['EMAIL_BACKEND']
|
||||
|
@ -105,4 +82,9 @@ STATIC_ROOT = os.path.join(BASE_DIR, 'collected-static')
|
|||
STATICFILES_DIRS = (
|
||||
os.path.join(BASE_DIR, 'static', 'build'),
|
||||
)
|
||||
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
|
||||
|
||||
WORDPRESS_URL = "realorangeone.wordpress.com"
|
||||
|
||||
# Generate config data
|
||||
from project.common.data import generate_config
|
||||
DEFAULT_CONTEXT, PAGE_CONTEXT, PAGE_SWITCH = generate_config(BASE_DIR)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
|
@ -1,27 +0,0 @@
|
|||
from django.db import models
|
||||
import uuid
|
||||
|
||||
|
||||
class Device(models.Model):
|
||||
device_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
device_name = models.CharField(max_length=50, blank=False, null=True)
|
||||
friendly_name = models.CharField(max_length=50, blank=False, null=True, unique=True)
|
||||
model_name = models.CharField(max_length=50, blank=False, null=True, unique=True)
|
||||
description = models.TextField(blank=True, null=True)
|
||||
computer = models.ForeignKey('setup.Computer')
|
||||
|
||||
|
||||
|
||||
class Computer(models.Model):
|
||||
computer_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
CPU = models.TextField(max_length=30, blank=False, null=True, verbose_name="Processor")
|
||||
GPU = models.TextField(max_length=40, blank=True, null=True, verbose_name="Graphics Card")
|
||||
RAM = models.IntegerField(blank=False, null=True)
|
||||
|
||||
|
||||
|
||||
class Peripheral(models.Model):
|
||||
peripheral_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
name = models.CharField(max_length=40, blank=False, null=True)
|
||||
model_name = models.CharField(max_length=100, blank=False, null=True)
|
||||
device = models.ForeignKey('setup.Device')
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,7 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^desk', views.DeskView.as_view(), name="desk"),
|
||||
url(r'^', views.SetupIndexView.as_view(), name="index")
|
||||
]
|
|
@ -1,11 +0,0 @@
|
|||
from django.views.generic import TemplateView
|
||||
from project.common.views import CustomHeaderBG
|
||||
|
||||
|
||||
class SetupIndexView(TemplateView):
|
||||
template_name = "setup/index.html"
|
||||
|
||||
|
||||
class DeskView(CustomHeaderBG.Template):
|
||||
template_name = "setup/my-rig.html"
|
||||
header_BG = "https://c1.staticflickr.com/1/557/18312934624_b51a541594_h.jpg"
|
|
@ -1,15 +1,7 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.contrib import admin
|
||||
from project.pages.views import Custom404View
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^site-admin/', include(admin.site.urls)),
|
||||
url(r'^student-robotics/', include('project.robotics.urls', namespace='robotics')),
|
||||
url(r'^projects/', include('project.projects.urls', namespace='projects')),
|
||||
url(r'^media/', include('project.media.urls', namespace='media')),
|
||||
url(r'^setup/', include('project.setup.urls', namespace='setup')),
|
||||
url(r'^college/', include('project.college.urls', namespace='college')),
|
||||
url(r'^blog/', include('project.blog.urls', namespace='blog')),
|
||||
url(r'', include('project.pages.urls', namespace='pages'))
|
||||
]
|
||||
|
||||
handler404 = Custom404View
|
|
@ -1,11 +1,3 @@
|
|||
"""
|
||||
WSGI config for twm project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
||||
"""
|
||||
import os
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
Django==1.8.3
|
||||
beautifulsoup4==4.4.1
|
||||
coverage==4.0.3
|
||||
colorama==0.3.6
|
||||
Django==1.8.11
|
||||
dj-database-url==0.3.0
|
||||
django-bootstrap-form==3.2
|
||||
djangorestframework==3.2.0
|
||||
djorm-ext-pgfulltext==0.10
|
||||
flake8==2.4.1
|
||||
pep8==1.5.7
|
||||
pycrypto==2.6.1
|
||||
pyflakes==0.8.1
|
||||
six==1.9.0
|
||||
waitress==0.8.9
|
||||
whitenoise==2.0.2
|
||||
flake8==2.5.0
|
||||
iso8601==0.1.11
|
||||
markdown2==2.3.0
|
||||
PyYAML==3.11
|
||||
requests==2.9.1
|
||||
requests-mock==0.7.0
|
||||
whitenoise==2.0.6
|
||||
waitress==0.8.10
|
||||
|
|
68
runtests
68
runtests
|
@ -1,7 +1,67 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env python3
|
||||
import coverage
|
||||
import os, sys
|
||||
import subprocess
|
||||
from colorama import Fore, init
|
||||
|
||||
set -e
|
||||
|
||||
export PATH=env/bin:${PATH}
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
|
||||
from django.core.management import execute_from_command_line
|
||||
init(autoreset=True)
|
||||
|
||||
flake8 project --ignore=E128,E501 --exclude="migrations,settings,*/wsgi.py"
|
||||
|
||||
bin_dir = os.path.abspath(os.path.join(sys.executable, os.path.pardir))
|
||||
PERCENTAGE = 95
|
||||
EXIT_CODE = 0
|
||||
|
||||
|
||||
def check_if_exit_code():
|
||||
if EXIT_CODE != 0:
|
||||
print("\n{}Tests Failed. {}Please check messages above and then re-run the command.".format(Fore.RED, Fore.YELLOW))
|
||||
exit(EXIT_CODE)
|
||||
|
||||
|
||||
cov = coverage.Coverage(
|
||||
source=["project"],
|
||||
omit=["*/wsgi.py", "*/settings.py", "*/migrations/*.py", "*/__init__*", "*/tests.py"]
|
||||
)
|
||||
cov.start()
|
||||
|
||||
print(Fore.YELLOW + "Running Tests...")
|
||||
execute_from_command_line([sys.argv[0], 'test'])
|
||||
cov.stop()
|
||||
|
||||
print("{}Tests Complete. {}Collecting Coverage...".format(Fore.GREEN, Fore.YELLOW))
|
||||
cov.save()
|
||||
cov.html_report()
|
||||
covered = cov.report()
|
||||
if covered < PERCENTAGE:
|
||||
print("{}ERROR: Your coverage needs to be higher. Current coverage: {}%. Required: {}%.".format(Fore.RED, covered, PERCENTAGE))
|
||||
EXIT_CODE = 1
|
||||
|
||||
check_if_exit_code()
|
||||
print("{}Coverage Complete. {}Linting...".format(Fore.GREEN, Fore.YELLOW))
|
||||
|
||||
|
||||
FLAKE8_IGNORE = '--ignore=E128,E501,E401,E402'
|
||||
try:
|
||||
subprocess.check_output([os.path.join(bin_dir, 'flake8'), 'project', FLAKE8_IGNORE, '--exclude=migrations,settings,wsgi.py,__init__.py'])
|
||||
subprocess.check_output([os.path.join(bin_dir, 'flake8'), 'scripts', FLAKE8_IGNORE])
|
||||
subprocess.check_output([os.path.join(bin_dir, 'flake8'), sys.argv[0], FLAKE8_IGNORE])
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(Fore.RED, e.output.decode())
|
||||
EXIT_CODE = 1
|
||||
|
||||
check_if_exit_code()
|
||||
print("{}All Python tests passed! {}Testing Static Files...".format(Fore.GREEN, Fore.YELLOW))
|
||||
|
||||
|
||||
EXIT_CODE = os.system('npm test')
|
||||
check_if_exit_code()
|
||||
|
||||
print("{}All static tests passed! {}Running spell check...".format(Fore.GREEN, Fore.YELLOW))
|
||||
|
||||
EXIT_CODE = os.system('')
|
||||
check_if_exit_code()
|
||||
|
||||
print("{}All Tests Passed!".format(Fore.GREEN))
|
||||
|
|
48
scripts/build-js.sh
Normal file → Executable file
48
scripts/build-js.sh
Normal file → Executable file
|
@ -1,18 +1,44 @@
|
|||
#!/usr/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
cp node_modules/bootstrap/dist/js/bootstrap.js static/src/js/lib/
|
||||
cp node_modules/skrollr/src/skrollr.js static/src/js/lib/
|
||||
if [[ $BUILD_PRODUCTION ]]
|
||||
then
|
||||
echo ">>> WARNING: Building in Production Mode!"
|
||||
fi
|
||||
|
||||
mkdir -p static/build/js/lib
|
||||
|
||||
if [[ $BUILD_PRODUCTION ]]
|
||||
then
|
||||
echo ">> Compressing Libraries..."
|
||||
uglifyjs node_modules/bootstrap/dist/js/bootstrap.js --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/lib/bootstrap.js
|
||||
uglifyjs static/build/js/lib/* --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/libs.js
|
||||
else
|
||||
echo ">> Building Libraries..."
|
||||
cp node_modules/bootstrap/dist/js/bootstrap.js static/build/js/lib/bootstrap.js
|
||||
uglifyjs static/build/js/lib/* --screw-ie8 --stats --keep-fnames -o static/build/js/libs.js
|
||||
fi
|
||||
|
||||
rm -rf static/build/js/lib
|
||||
|
||||
if [[ $BUILD_PRODUCTION ]]
|
||||
then
|
||||
echo ">> Compressing jQuery..."
|
||||
uglifyjs node_modules/jquery/dist/jquery.js --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/jquery.js
|
||||
else
|
||||
echo ">> Building jQuery..."
|
||||
uglifyjs node_modules/jquery/dist/jquery.js --screw-ie8 --stats --keep-fnames -o static/build/js/jquery.js
|
||||
fi
|
||||
|
||||
echo ">> Building Libraries..."
|
||||
uglifyjs node_modules/jquery/dist/jquery.js --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/jquery.js
|
||||
uglifyjs node_modules/markdown/lib/markdown.js --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/markdown.js
|
||||
uglifyjs static/src/js/lib/* --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/libs.js
|
||||
|
||||
echo ">> Building Application JS..."
|
||||
browserify -t reactify static/src/js/app.js -o static/build/js/app.js
|
||||
# uglifyjs static/build/js/app.js --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/app.js
|
||||
browserify -t [ babelify --presets [ es2015 react ] ] static/src/js/app.js -o static/build/js/app.js
|
||||
|
||||
echo ">> Building Global Utilities..."
|
||||
uglifyjs static/src/js/utils.js --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/utils.js
|
||||
if [[ $BUILD_PRODUCTION ]]
|
||||
then
|
||||
echo ">> Compressing Application..."
|
||||
uglifyjs static/build/js/app.js --compress --screw-ie8 --define --stats --keep-fnames -o static/build/js/app.js
|
||||
fi
|
||||
|
||||
echo "> JS Built!"
|
||||
|
|
22
scripts/build-less.sh
Executable file
22
scripts/build-less.sh
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $BUILD_PRODUCTION ]]
|
||||
then
|
||||
echo ">>> WARNING: Building in Production Mode!"
|
||||
fi
|
||||
|
||||
echo ">> Building LESS..."
|
||||
lessc --silent static/src/less/style.less static/build/css/style.css
|
||||
|
||||
echo ">> Post-Processing..."
|
||||
postcss -u autoprefixer -o static/build/css/style.css static/build/css/style.css
|
||||
|
||||
if [[ $BUILD_PRODUCTION ]]
|
||||
then
|
||||
echo ">> Compressing LESS..."
|
||||
cleancss -d --s0 -o static/build/css/style.css static/build/css/style.css
|
||||
fi
|
||||
|
||||
echo "> LESS Built!"
|
15
scripts/clean.sh
Executable file
15
scripts/clean.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
echo ">> Removing VirtualEnv..."
|
||||
rm -rf env/
|
||||
|
||||
echo ">> Removing Node Modules..."
|
||||
rm -rf node_modules/
|
||||
|
||||
echo ">> Removing Static Build Directory..."
|
||||
rm -rf static/build/
|
||||
|
||||
echo "> Cleaning Complete."
|
24
scripts/fresh.sh
Executable file
24
scripts/fresh.sh
Executable file
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
echo ">> Removing VirtualEnv..."
|
||||
rm -rf env/
|
||||
|
||||
echo ">> Removing Collected Static Files..."
|
||||
rm -rf collected-static/
|
||||
|
||||
echo ">> Removing Private Data..."
|
||||
rm -rf private/
|
||||
|
||||
echo ">> Removing Node Modules..."
|
||||
rm -rf node_modules/
|
||||
|
||||
echo ">> Removing Static Build Directory..."
|
||||
rm -rf static/build/
|
||||
|
||||
echo ">> Removing Stray Files and Folders..."
|
||||
rm -rf htmlcov/ .coverage
|
||||
|
||||
echo "> Much Fresher!"
|
9
scripts/get-private-data.sh
Executable file
9
scripts/get-private-data.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
echo ">> Removing old Private Data..."
|
||||
rm -rf private/
|
||||
|
||||
echo ">> Getting Private Data..."
|
||||
git clone git@bitbucket.org:TheOrangeOne/theorangeone.net-site-private-data.git --branch master --single-branch private/
|
|
@ -1,14 +0,0 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo ">> Removing old Private data..."
|
||||
rm -rf private/*
|
||||
mkdir private/
|
||||
cd private/
|
||||
|
||||
echo ">> Cloning Private Repo..."
|
||||
git clone git@bitbucket.org:TheOrangeOne/theorangeone.net-site-private-data.git
|
||||
|
||||
|
||||
echo ">> That's it for now..."
|
BIN
static/src/img/SR-logo-banner.png
Normal file
BIN
static/src/img/SR-logo-banner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 105 KiB |
BIN
static/src/img/logo-transparent.png
Normal file
BIN
static/src/img/logo-transparent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 237 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
BIN
static/src/img/projects/collyers-logo.gif
Normal file
BIN
static/src/img/projects/collyers-logo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
BIN
static/src/img/projects/kermit-typing.gif
Normal file
BIN
static/src/img/projects/kermit-typing.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 MiB |
|
@ -1,14 +1,24 @@
|
|||
var React = require('react');
|
||||
var indexCarousel = require('./components/indexCarousel.js');
|
||||
import './events.js';
|
||||
import './globals.js';
|
||||
|
||||
require('./events.js');
|
||||
import 'whatwg-fetch';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
if ($('#index-carousel-container').length == 1) {
|
||||
React.render(indexCarousel, $("#index-carousel-container")[0]);
|
||||
import NavBar from './components/navbar/navbar';
|
||||
import Breadcrumbs from './components/breadcrumbs';
|
||||
import renderImagePanels from './components/image-panel';
|
||||
|
||||
renderImagePanels();
|
||||
|
||||
if ($('navbar').length > 0) {
|
||||
React.render(<NavBar />, $('navbar')[0]);
|
||||
}
|
||||
|
||||
$(window).load(function(){
|
||||
$(window).trigger('scroll').trigger('resize');
|
||||
var s = skrollr.init();
|
||||
});
|
||||
if ($('#breadcrumbs').length > 0) {
|
||||
React.render(<Breadcrumbs />, $('#breadcrumbs')[0]);
|
||||
}
|
||||
|
||||
if ($('.header h1').text()) {
|
||||
$('.markdown-content h1').eq(0).hide();
|
||||
}
|
||||
|
|
33
static/src/js/components/breadcrumbs.js
Normal file
33
static/src/js/components/breadcrumbs.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import React from 'react';
|
||||
|
||||
export default class Breadcrumbs extends React.Component {
|
||||
render() {
|
||||
const loc = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname;
|
||||
const urlParts = Object.freeze(loc.split('/').slice(1));
|
||||
if (urlParts.length < 2) {
|
||||
return null;
|
||||
}
|
||||
var elements = [];
|
||||
for (var i = 0; i < urlParts.length; i++) {
|
||||
var dirs = [];
|
||||
for (var j = 0; j <= i; j++) {
|
||||
dirs.push(urlParts[j]);
|
||||
}
|
||||
if (i === (urlParts.length - 1)) {
|
||||
elements.push(
|
||||
<li className="active">{urlParts[i]}</li>
|
||||
);
|
||||
} else {
|
||||
var url = '/' + dirs.join('/') + '/';
|
||||
elements.push(
|
||||
<li><a href={url}>{urlParts[i]}</a></li>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<ol className="breadcrumb">
|
||||
{ elements }
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
}
|
24
static/src/js/components/image-panel.js
Normal file
24
static/src/js/components/image-panel.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
export default function renderImagePanels() {
|
||||
$('.image-panel').each(function () {
|
||||
const element = $(this);
|
||||
if (!element.data('image')) { // if it doesnt have an image, ignore it.
|
||||
return;
|
||||
}
|
||||
|
||||
element.css('background-image', 'url("' + element.data('image') + '")');
|
||||
|
||||
let height;
|
||||
switch (element.data('size')) {
|
||||
case 'small':
|
||||
height = '30';
|
||||
break;
|
||||
default:
|
||||
case 'medium':
|
||||
height = '60';
|
||||
break;
|
||||
case 'large':
|
||||
height = '100';
|
||||
}
|
||||
element.css('height', `${height}vh`);
|
||||
});
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
var React = require('react');
|
||||
var Bootstrap = require('react-bootstrap');
|
||||
|
||||
var Carousel = Bootstrap.Carousel;
|
||||
var CarouselItem = Bootstrap.CarouselItem;
|
||||
|
||||
const indexCarousel = (
|
||||
<Carousel>
|
||||
<CarouselItem>
|
||||
<div className='carousel-image'></div>
|
||||
<div className='carousel-caption'>
|
||||
<h3>Setup</h3>
|
||||
<p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>
|
||||
</div>
|
||||
</CarouselItem>
|
||||
|
||||
<CarouselItem>
|
||||
<div className='carousel-image'></div>
|
||||
<div className='carousel-caption'>
|
||||
<h3>Student Robotics</h3>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
||||
</div>
|
||||
</CarouselItem>
|
||||
</Carousel>
|
||||
);
|
||||
|
||||
module.exports = indexCarousel;
|
20
static/src/js/components/navbar/dropdown.js
Normal file
20
static/src/js/components/navbar/dropdown.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import React from 'react';
|
||||
|
||||
export default class Dropdown extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<li className="dropdown">
|
||||
<a className="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false">
|
||||
{ this.props.title } <i className="icon ion-ios-arrow-up navbar-icon h4 hidden-sm"></i>
|
||||
</a>
|
||||
<ul className="dropdown-menu dropup">
|
||||
{ this.props.children }
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
28
static/src/js/components/navbar/header.js
Normal file
28
static/src/js/components/navbar/header.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import React from 'react';
|
||||
|
||||
export default class Header extends React.Component {
|
||||
render() {
|
||||
const items = [0, 1, 2];
|
||||
var iconBars = items.map(function (item) {
|
||||
return (
|
||||
<span className="icon-bar" key={item} />
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div className="navbar-header">
|
||||
<button type="button"
|
||||
className="navbar-toggle collapsed"
|
||||
data-toggle="collapse"
|
||||
data-target="#navbar"
|
||||
aria-expanded="false" >
|
||||
<span className="sr-only">Toggle navigation</span>
|
||||
{{ iconBars }}
|
||||
</button>
|
||||
<a className="navbar-brand visible-xs">
|
||||
<i className="icon ion-compass" />
|
||||
Navigation
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
23
static/src/js/components/navbar/item.js
Normal file
23
static/src/js/components/navbar/item.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
|
||||
|
||||
export default class Item extends React.Component {
|
||||
render() {
|
||||
const href = this.props.href.endsWith('/') ? this.props.href : this.props.href + '/';
|
||||
let icon;
|
||||
if (this.props.icon) {
|
||||
if (this.props.icon.startsWith('ion')) {
|
||||
icon = (
|
||||
<i className={'icon ' + this.props.icon} />
|
||||
);
|
||||
} else if (this.props.icon.startsWith('glyphicon')) {
|
||||
icon = (
|
||||
<span className={'glyphicon ' + this.props.icon} aria-hidden="true" />
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<li><a href={href}>{icon}{this.props.children}</a></li>
|
||||
);
|
||||
}
|
||||
}
|
74
static/src/js/components/navbar/navbar.js
Normal file
74
static/src/js/components/navbar/navbar.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
import React from 'react';
|
||||
import Header from './header';
|
||||
import Dropdown from './dropdown';
|
||||
import Item from './item';
|
||||
|
||||
export default class NavBar extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<span>
|
||||
<div id="navbar-anchor" />
|
||||
<div id="navbar-container" className="align">
|
||||
<nav className="navbar navbar-inverse">
|
||||
<div className="container-fluid">
|
||||
<Header />
|
||||
<div className="collapse navbar-collapse" id="navbar">
|
||||
<ul className="nav navbar-nav home-button hidden-sm hidden-md">
|
||||
<Item href="/" icon="ion-home" />
|
||||
</ul>
|
||||
<ul className="nav navbar-nav" id="navigation">
|
||||
<Dropdown title="Projects">
|
||||
<Item href="/projects/yoga-pal/" icon="ion-laptop">Yoga Pal</Item>
|
||||
<Item href="/projects/bsod-enabler/" icon="ion-ios-monitor">BSOD Enabler</Item>
|
||||
<Item href="/projects/hipchat-emoticons-for-all/" icon="ion-chatbox-working">
|
||||
Hipchat Emoticons for All
|
||||
</Item>
|
||||
<Item href="#" icon="ion-social-windows">Custom PC</Item>
|
||||
<Item href="/projects/" icon="ion-android-more-vertical">All Projects...</Item>
|
||||
</Dropdown>
|
||||
<Dropdown title="Code">
|
||||
<Item href="#" icon="ion-code-working">Code Challenges</Item>
|
||||
<Item href="#" icon="ion-ios-circle-filled">Pi Time Lapse</Item>
|
||||
<Item href="/projects/wiki-game-solver/" icon="ion-ios-game-controller-a">The Wiki Game Solver</Item>
|
||||
</Dropdown>
|
||||
<Dropdown title="College">
|
||||
<Item href="/robotics/">Student Robotics</Item>
|
||||
<Item href="/college/attack-on-blocks/" icon="ion-cube">Attack on Blocks Game</Item>
|
||||
<Item href="/college/student-server/" icon="glyphicon-hdd">Student Server</Item>
|
||||
<Item href="#" icon="ion-ios-paper">EPQ</Item>
|
||||
<Item href="#">Wall of Sheep</Item>
|
||||
</Dropdown>
|
||||
<Dropdown title="Setup">
|
||||
<Item href="#">💁 Desk</Item>
|
||||
<Item href="#" icon="ion-briefcase">Work</Item>
|
||||
<Item href="#" icon="ion-model-s">On The Go</Item>
|
||||
<Item href="#" icon="ion-android-phone-portrait">Devices</Item>
|
||||
<Item href="#">Servers</Item>
|
||||
</Dropdown>
|
||||
<Dropdown title="Work">
|
||||
<Item href="#" icon="ion-form-repo">Projects</Item>
|
||||
<Item href="#" icon="ion-android-desktop">Setup</Item>
|
||||
</Dropdown>
|
||||
<Dropdown title="Media">
|
||||
<Item
|
||||
href="https://www.youtube.com/user/TheOrangeOneOfficial"
|
||||
icon="ion-social-youtube">
|
||||
YouTube Channel
|
||||
</Item>
|
||||
<Item href="/blog/" icon="ion-social-rss">Blog</Item>
|
||||
<Item href="https://www.flickr.com/photos/theorangeone/" icon="ion-social-camera">Gallery</Item>
|
||||
</Dropdown>
|
||||
<Item href="#">Links</Item>
|
||||
<Dropdown title="About">
|
||||
<Item href="/about/me/" icon="ion-android-person">Me</Item>
|
||||
<Item href="/about/website/" icon="ion-cloud">Website</Item>
|
||||
</Dropdown>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,16 +1,69 @@
|
|||
$(window).scroll(function() {
|
||||
position_navbar();
|
||||
/* global $ */
|
||||
var is_navbar_attached = false;
|
||||
|
||||
$(window).load(function() {
|
||||
$(window).trigger('scroll');
|
||||
});
|
||||
|
||||
function detach_navbar() {
|
||||
$('#navbar-container').removeClass('stick-top').addClass('align');
|
||||
$('.dropdown-menu').removeClass('dropdown').addClass('dropup');
|
||||
}
|
||||
|
||||
$(window).resize(function() {
|
||||
set_page_sizes();
|
||||
space_navbar();
|
||||
function attach_navbar() {
|
||||
$('#navbar-container').removeClass('align').addClass('stick-top');
|
||||
$('.dropdown-menu').removeClass('dropup').addClass('dropdown');
|
||||
}
|
||||
|
||||
function flip_dropdowns(obj, direction) {
|
||||
if (obj.hasClass('drop' + direction)) { return; }
|
||||
var reverse = ((direction === 'up') ? 'down' : 'up');
|
||||
obj.removeClass('drop' + reverse).addClass('drop' + direction);
|
||||
obj.prev().find('i').removeClass('ion-ios-arrow-' + reverse).addClass('ion-ios-arrow-' + direction);
|
||||
}
|
||||
|
||||
function position_navbar() {
|
||||
if ($(window).width() < 862) { // @screen-sm
|
||||
$('.navbar-icon').removeClass('ion-ios-arrow-up').addClass('ion-ios-arrow-down');
|
||||
return;
|
||||
}
|
||||
if ($(window).scrollTop() > $('#navbar-anchor').offset().top) {
|
||||
if (!is_navbar_attached) {
|
||||
attach_navbar();
|
||||
is_navbar_attached = true;
|
||||
}
|
||||
} else if (is_navbar_attached) {
|
||||
detach_navbar();
|
||||
is_navbar_attached = false;
|
||||
}
|
||||
$('.dropdown-menu').each(function() {
|
||||
var direction = ($(this).height() + 10 < $('nav').offset().top - $(window).scrollTop()) ? 'up' : 'down';
|
||||
flip_dropdowns($(this), direction);
|
||||
});
|
||||
}
|
||||
|
||||
$(function() { // https://css-tricks.com/snippets/jquery/smooth-scrolling/
|
||||
$('a[href*=#]:not([href=#])').click(function() {
|
||||
if ($(this).data('toggle') === 'collapse') {
|
||||
return true;
|
||||
}
|
||||
if (location.pathname.replace(/^\//, '') === this.pathname.replace(/^\//, '')
|
||||
&& location.hostname === this.hostname) {
|
||||
var target = $(this.hash);
|
||||
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
|
||||
if (target.length) {
|
||||
$('html,body').animate({
|
||||
scrollTop: target.offset().top
|
||||
}, 1000);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$("#page-down").click(function() {
|
||||
$('html, body').animate({
|
||||
scrollTop: $("#navbar-anchor").offset().top
|
||||
}, 750);
|
||||
$('a[href="soon"]').click(function (e) {
|
||||
e.preventDefault();
|
||||
alert('Content coming soon, stand by!');
|
||||
});
|
||||
|
||||
$(window).scroll(position_navbar);
|
||||
|
|
7
static/src/js/globals.js
Normal file
7
static/src/js/globals.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
window.updateTitle = function (value) {
|
||||
document.title = value + ' | TheOrangeOne';
|
||||
};
|
||||
|
||||
if ($('.header h1').length) {
|
||||
window.updateTitle($('.header h1').text());
|
||||
}
|
2363
static/src/js/lib/bootstrap.js
vendored
2363
static/src/js/lib/bootstrap.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,83 +0,0 @@
|
|||
var is_navbar_attached = false;
|
||||
function position_navbar() {
|
||||
if ($(window).width() < 862) { // @screen-sm
|
||||
$('.navbar-icon').removeClass('ion-ios-arrow-up').addClass('ion-ios-arrow-down');
|
||||
return;
|
||||
}
|
||||
if ($(window).scrollTop() > $('#navbar-anchor').offset().top) {
|
||||
if(!is_navbar_attached) {attach_navbar(); is_navbar_attached = true;}
|
||||
} else if (is_navbar_attached) {
|
||||
detach_navbar();
|
||||
is_navbar_attached = false;
|
||||
}
|
||||
$('.dropdown-menu').each(function(){
|
||||
direction = ($(this).height() + 10 < $('nav').offset().top - $(window).scrollTop()) ? 'up' : 'down';
|
||||
flip_dropdowns($(this), direction);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function detach_navbar() {
|
||||
$('#navbar-container').removeClass('stick-top').addClass('align');
|
||||
$('.dropdown-menu').removeClass('dropdown').addClass('dropup');
|
||||
}
|
||||
|
||||
|
||||
function set_page_sizes() {
|
||||
win_height = $(window).height();
|
||||
win_width = $(window).width();
|
||||
$('.page-height').each(function() {
|
||||
$(this).height(win_height);
|
||||
});
|
||||
$('.page-width').each(function() {
|
||||
$(this).width(win_width);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function attach_navbar() {
|
||||
$('#navbar-container').removeClass('align').addClass('stick-top');
|
||||
$('.dropdown-menu').removeClass('dropup').addClass('dropdown');
|
||||
}
|
||||
|
||||
|
||||
function flip_dropdowns(obj, direction) {
|
||||
if (obj.hasClass('drop'+direction)){ return; }
|
||||
reverse = direction == 'up' ? 'down' : 'up';
|
||||
obj.removeClass('drop' + reverse).addClass('drop' + direction);
|
||||
obj.prev().children().removeClass('ion-ios-arrow-' + reverse).addClass('ion-ios-arrow-' + direction);
|
||||
}
|
||||
|
||||
|
||||
function space_navbar() { //This really should be CSS!
|
||||
if ($(window).width() < 862) {return;} // @screen-sm
|
||||
nav_width = $('#navigation').outerWidth(true);
|
||||
full_width = $('nav > .container-fluid').outerWidth(true) - $('.home-button').outerWidth(true);
|
||||
margin = (full_width - nav_width) / 2;
|
||||
$('#navigation').css('margin-left', margin);
|
||||
}
|
||||
|
||||
|
||||
function checkDomain(url) {
|
||||
if ( url.indexOf('//') === 0 ) { url = location.protocol + url; }
|
||||
return url.toLowerCase().replace(/([a-z])?:\/\//,'$1').split('/')[0];
|
||||
}
|
||||
|
||||
|
||||
function isExternal(url) {
|
||||
return ( ( url.indexOf(':') > -1 || url.indexOf('//') > -1 ) && checkDomain(location.href) !== checkDomain(url) );
|
||||
}
|
||||
|
||||
|
||||
function is_on_screen(elm) {
|
||||
var vpH = $(window).height(), // Viewport Height
|
||||
st = $(window).scrollTop(), // Scroll Top
|
||||
y = $(elm).offset().top,
|
||||
elementHeight = $(elm).height();
|
||||
return ((y < (vpH + st)) && (y > (st - elementHeight)));
|
||||
}
|
||||
|
||||
|
||||
function navTo(url){
|
||||
location.href=url;
|
||||
}
|
6
static/src/less/assets.less
Normal file
6
static/src/less/assets.less
Normal file
|
@ -0,0 +1,6 @@
|
|||
@btn-srobo-color: @gray-lighter;
|
||||
@btn-srobo-bg: #253571;
|
||||
@btn-srobo-border: darken(@btn-srobo-bg, 5%);
|
||||
.btn-srobo {
|
||||
.button-variant(@btn-srobo-color; @btn-srobo-bg; @btn-srobo-border);
|
||||
}
|
8
static/src/less/components.less
Normal file
8
static/src/less/components.less
Normal file
|
@ -0,0 +1,8 @@
|
|||
.image-panel {
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
197
static/src/less/homepage.less
Normal file
197
static/src/less/homepage.less
Normal file
|
@ -0,0 +1,197 @@
|
|||
@blueprint-logo: url(http://ultimatestorytellingblueprint.com/wp-content/uploads/2014/07/Blueprint-Background1.jpg);
|
||||
@container-inset: 35px;
|
||||
|
||||
body.index {
|
||||
#header {
|
||||
height: 100vh;
|
||||
background: #232323;
|
||||
background-size: cover;
|
||||
background-position: fixed;
|
||||
.jumbotron {
|
||||
margin-top: 19vh;
|
||||
text-align: center;
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
.box-shadow(initial);
|
||||
h1 {
|
||||
margin-bottom: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
p.scroll-icon {
|
||||
margin-top: 45px;
|
||||
}
|
||||
i.icon {
|
||||
cursor: pointer;
|
||||
font-size: 30px;
|
||||
.transition(color 0.4s);
|
||||
&:hover {
|
||||
color: #ff7f00;
|
||||
}
|
||||
}
|
||||
img {
|
||||
height: 275px;
|
||||
}
|
||||
}
|
||||
}
|
||||
#intro-text {
|
||||
background-color: #333;
|
||||
.container {
|
||||
text-align: center;
|
||||
margin-top: @container-inset;
|
||||
margin-bottom: @container-inset;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
#twitter-feed {
|
||||
text-align: center;
|
||||
.container {
|
||||
margin-top: @container-inset;
|
||||
margin-bottom: @container-inset;
|
||||
}
|
||||
.twitter-timeline {
|
||||
height: 65vh !important; // Because twitter uses inline styles.
|
||||
.box-shadow(4px 5px 2px 0 rgba(0,0,0,0.4));
|
||||
}
|
||||
.twitter-icon {
|
||||
text-align: center;
|
||||
font-size: 175px;
|
||||
height: 65vh;
|
||||
position: relative;
|
||||
.icon {
|
||||
position: absolute;
|
||||
text-shadow: 4px 5px 2px rgba(0,0,0,0.4);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
.transition(color 0.6s);
|
||||
&:hover {
|
||||
color: #55ACEE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#project-thumbnails {
|
||||
background-image: @blueprint-logo;
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
& > div > .row {
|
||||
margin-top: @container-inset;
|
||||
margin-bottom: @container-inset;
|
||||
& > h1 {
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.thumbnail {
|
||||
padding: 15px;
|
||||
height: 275px;
|
||||
text-align: center;
|
||||
&.larger {
|
||||
.inner {
|
||||
position: relative;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
h1, h2 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
&.project h2 {
|
||||
@media (min-width: @screen-sm-min) {
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 45%;
|
||||
}
|
||||
h3 {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.caption {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* @group project-images */
|
||||
.project-image {
|
||||
.wrapper {
|
||||
color: white;
|
||||
margin: 0 auto;
|
||||
cursor: pointer;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
.box-shadow(0px 4px 5px 2px rgba(0,0,0,0.7));
|
||||
|
||||
&:hover .project {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-xs-max) {
|
||||
&, & .project {
|
||||
height: 240px;
|
||||
width: 240px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: @screen-sm-min) {
|
||||
&, & .project {
|
||||
height: 210px;
|
||||
width: 210px;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: @screen-md-min) {
|
||||
&, & .project {
|
||||
height: 280px;
|
||||
width: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
& .project {
|
||||
padding: 8%;
|
||||
.flexbox();
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.transition(~"opacity 0.5s ease-in");
|
||||
opacity: 0;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
text-align: center;
|
||||
|
||||
@media screen and (max-width: @screen-xs-max) {
|
||||
p, a.btn {
|
||||
font-size: 14px;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
h4 {
|
||||
font-size: 25px;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: @screen-sm-min) {
|
||||
p, a.btn {
|
||||
font-size: 13px;
|
||||
}
|
||||
h4 {
|
||||
font-size: 21px;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: @screen-md-min) {
|
||||
p, a.btn {
|
||||
font-size: 17px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
h4 {
|
||||
font-size: 25px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* @end project-images */
|
136
static/src/less/navbar.less
Normal file
136
static/src/less/navbar.less
Normal file
|
@ -0,0 +1,136 @@
|
|||
#navigation {
|
||||
@media (min-width: @screen-xs-max) {
|
||||
.flexbox();
|
||||
justify-content: center;
|
||||
float: none;
|
||||
}
|
||||
& a {
|
||||
.transition(~"ease-in-out .3s color");
|
||||
}
|
||||
& > li {
|
||||
max-height: @navbar-height;
|
||||
@media (min-width: @screen-md-min) {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
.dropdown-toggle, & > li > a {
|
||||
font-size: 19px;
|
||||
max-height: @navbar-height;
|
||||
}
|
||||
.dropdown-menu {
|
||||
.transition(~"ease-in-out .2s all");
|
||||
@media (min-width: @screen-sm) {
|
||||
right: auto;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
& > li > a {
|
||||
font-size: 15px;
|
||||
}
|
||||
&.dropup {
|
||||
bottom: 100%;
|
||||
top: initial;
|
||||
}
|
||||
&.dropdown {
|
||||
top: 100%;
|
||||
bottom: initial;
|
||||
}
|
||||
.open & {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.navbar {
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
.home-button a {
|
||||
.transition(~"ease-in-out .3 all");
|
||||
}
|
||||
@media (min-height: @screen-sm-min) {
|
||||
max-height: @navbar-height;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-nav.nav {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.navbar-toggle {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
#navbar-container {
|
||||
margin: 0;
|
||||
z-index: 10000;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
width: 96%;
|
||||
left: 2%;
|
||||
}
|
||||
@media (min-width: @screen-sm-min) {
|
||||
width: 100%;
|
||||
}
|
||||
i + *, .glyphicon + * {
|
||||
margin-left: 5px;
|
||||
}
|
||||
& .container-fluid{
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
&.align {
|
||||
@media (min-width: @screen-sm) {
|
||||
position: initial;
|
||||
height: @navbar-height;
|
||||
margin-top: -50px;
|
||||
}
|
||||
@media (max-width: @screen-sm) {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 95%;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#navbar-anchor {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
@media (min-width: @screen-xs-max) {
|
||||
.home-button {
|
||||
margin-right: 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
#navbar {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.stick-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
// /* @group Header Navbar*/
|
||||
// @media (min-width: @screen-sm-min) {
|
||||
// .header {
|
||||
// #navbar-container {
|
||||
// margin: 0 auto;
|
||||
// &:not(.stick-top) {
|
||||
// position: initial;
|
||||
// }
|
||||
// &.stick-top {
|
||||
// width: 100%;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// /* @end Header Navbar*/
|
|
@ -1,99 +1,31 @@
|
|||
@import "node_modules/less-mixins/index.less";
|
||||
@import "node_modules/bootstrap/less/bootstrap";
|
||||
@import "node_modules/ionicons/less/ionicons";
|
||||
@import "node_modules/bootstrap/less/theme";
|
||||
@import "node_modules/ionicons-pre/less/ionicons";
|
||||
@import url(https://fonts.googleapis.com/css?family=Roboto:400,300,400italic,700);
|
||||
@import "variables";
|
||||
|
||||
/* @group mixins */
|
||||
|
||||
.transition(@value) {
|
||||
-webkit-transition: @value;
|
||||
-moz-transition: @value;
|
||||
-o-transition: @value;
|
||||
-ms-transition: @value;
|
||||
transition: @value;
|
||||
}
|
||||
|
||||
.box-shadow(@value) {
|
||||
-webkit-box-shadow: @value;
|
||||
-moz-box-shadow: @value;
|
||||
box-shadow: @value;
|
||||
}
|
||||
|
||||
|
||||
/* @end mixins */
|
||||
|
||||
/* @group Global Transitions */
|
||||
@import (inline) "node_modules/animate.css/animate.css";
|
||||
@import 'homepage';
|
||||
@import 'variables';
|
||||
@import 'navbar';
|
||||
@import 'assets';
|
||||
@import 'components';
|
||||
|
||||
/* @group Global */
|
||||
.btn {
|
||||
.transition(~"ease-in-out .2s background-color");
|
||||
.transition(~"ease-in-out .4s background-color");
|
||||
}
|
||||
|
||||
p > a {
|
||||
.transition(~"ease-in-out .20s ease");
|
||||
&:not(.no-line):not(.btn) {
|
||||
text-decoration: none;
|
||||
position:relative;
|
||||
|
||||
&::before {
|
||||
content: ' ';
|
||||
display: block;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: @link-color;
|
||||
.transition(~"ease-in-out .2s opacity, ease-in-out .2s background-color");
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
&::before {
|
||||
opacity: 1;
|
||||
background-color: @link-hover-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* @end Global Transitions */
|
||||
|
||||
/* @group Global Styles */
|
||||
|
||||
html, body{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
& > div {
|
||||
// margin-left: 0;
|
||||
padding-left: 0;
|
||||
a {
|
||||
.transition(color 0.4s);
|
||||
}
|
||||
}
|
||||
|
||||
.panel {
|
||||
margin-bottom: 0;
|
||||
& h3 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ol , ul{
|
||||
|
@ -103,61 +35,38 @@ ol , ul{
|
|||
}
|
||||
}
|
||||
|
||||
/* @end Global Styles */
|
||||
|
||||
/* @group Functional Clases */
|
||||
|
||||
.stick-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 10000;
|
||||
blockquote {
|
||||
font-size: @font-size-base + 1px;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
a.no-color-change {
|
||||
color: inherit;
|
||||
&:hover {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
/* @end Global */
|
||||
|
||||
.no-font {
|
||||
font-size: 0px;
|
||||
}
|
||||
/* @group Functional */
|
||||
|
||||
.full-height {
|
||||
height: 100%;
|
||||
.center-align {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.center-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.fix-image {
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.margin-bottom {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.black-text {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.white-text {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.drop-shadow {
|
||||
.box-shadow(0 0.4px 6px 0 rgba(0, 0, 0, 0.9));
|
||||
}
|
||||
|
||||
.mega-icon {
|
||||
font-size: 110px;
|
||||
text-align: center;
|
||||
margin-bottom: 0;
|
||||
cursor: default;
|
||||
|
||||
& ~ div.caption {
|
||||
padding-top: 0;
|
||||
|
@ -167,213 +76,158 @@ div.fix-image {
|
|||
}
|
||||
}
|
||||
|
||||
/* @end Functional Classes */
|
||||
/* @end Functional */
|
||||
|
||||
/* @group Header */
|
||||
|
||||
#header {
|
||||
margin: 0;
|
||||
background: url(../img/header-bg.png);
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
backgorund-position: center center;
|
||||
margin-bottom: 15px;
|
||||
color: @gray-lighter;
|
||||
& div.jumbotron.container {
|
||||
color: @gray-lighter;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 25%;
|
||||
background-color: transparent;
|
||||
& div.row {
|
||||
text-shadow: 0px 3px 3px rgba(0, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
.content-wrapper {
|
||||
min-height: %(~"calc(100% - %d)", @footer-height);
|
||||
}
|
||||
|
||||
#page-down {
|
||||
position: absolute;
|
||||
bottom: 20%;
|
||||
text-align: center !important;
|
||||
|
||||
& i {
|
||||
.transition(~"ease-in-out .30s color");
|
||||
|
||||
&:hover {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* @end Header */
|
||||
|
||||
/* @group Navigation Bar */
|
||||
|
||||
.dropdown-menu {
|
||||
@media (min-width: @screen-sm) {
|
||||
right: auto;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
opacity: 0;
|
||||
.transition(~"ease-in-out .2s all");
|
||||
}
|
||||
&.dropup {
|
||||
bottom: 100%;
|
||||
top: initial;
|
||||
}
|
||||
&.dropdown {
|
||||
top: 100%;
|
||||
bottom: initial;
|
||||
}
|
||||
.open & {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
#navigation {
|
||||
& a {
|
||||
.transition(~"ease-in-out .3s color");
|
||||
}
|
||||
& > li {
|
||||
@media (min-width: @screen-md-min) {
|
||||
margin-right: 23px;
|
||||
}
|
||||
@media (max-width: @screen-sm-max) {
|
||||
margin-right: 10px;
|
||||
margin-left: 11px;
|
||||
}
|
||||
& > a {
|
||||
@media (min-width: @screen-md-min) {
|
||||
padding: 15px 10px;
|
||||
}
|
||||
@media (max-width: @screen-sm-max) {
|
||||
padding: 15px 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-nav.nav {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#navbar-container {
|
||||
z-index: 0;
|
||||
& .container-fluid{
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
&.align {
|
||||
@media (min-width: @screen-sm) {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 52px;
|
||||
}
|
||||
@media (max-width: @screen-sm) {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#navbar-anchor {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
.home-button {
|
||||
margin-right: 15px !important;
|
||||
}
|
||||
|
||||
#navbar {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
/* @end Navigation Bar */
|
||||
|
||||
/* @group Footer */
|
||||
@footer-link-margin: 7px;
|
||||
@footer-height: 250px;
|
||||
footer {
|
||||
height: 100px;
|
||||
height: @footer-height;
|
||||
width: 100%;
|
||||
margin-top: 15px;
|
||||
background-color: black;
|
||||
color: @text-color;
|
||||
p:first-child {
|
||||
padding-top: 30px;
|
||||
margin-bottom: 0px;
|
||||
text-align: center;
|
||||
padding-top: 30px;
|
||||
color: white;
|
||||
background-color: #232323;
|
||||
a {
|
||||
color: #ff7f00;
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
p.footer-links > a {
|
||||
font-size: 12px;
|
||||
margin-top: -4px;
|
||||
margin-left: @footer-link-margin;
|
||||
margin-right: @footer-link-margin;
|
||||
.bar-links {
|
||||
margin: 0 7px;
|
||||
}
|
||||
.powered-by {
|
||||
font-size: @font-size-h6;
|
||||
}
|
||||
.social {
|
||||
font-size: 23px;
|
||||
margin: 0;
|
||||
padding: 7px;
|
||||
a {
|
||||
margin: 0 4px;
|
||||
color: white;
|
||||
&:hover {
|
||||
color: #ff7f00;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ci-badge {
|
||||
height: @font-size-h4;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* @end Footer */
|
||||
|
||||
/* @group Index */
|
||||
|
||||
@index-carousel-height: 525px;
|
||||
@index-carousel-width: 100%;
|
||||
#index-carousel-container {
|
||||
height: @index-carousel-height;
|
||||
width: @index-carousel-width;
|
||||
& div.carousel-item {
|
||||
height: @index-carousel-height;
|
||||
overflow: hidden;
|
||||
/* @group 404 */
|
||||
.four-o-four {
|
||||
.header {
|
||||
height: 15vh;
|
||||
font-size: 35px;
|
||||
text-align: center;
|
||||
}
|
||||
& div.carousel-image {
|
||||
width: @index-carousel-width;
|
||||
height: @index-carousel-height;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
& div.item:nth-child(1) div.carousel-image {
|
||||
background-image: url(https://farm1.staticflickr.com/557/18747807580_d01e8e877a_c.jpg);
|
||||
}
|
||||
& div.item:nth-child(2) div.carousel-image {
|
||||
background-image: url(https://farm9.staticflickr.com/8815/17122387228_8b59d46392_b.jpg);
|
||||
}
|
||||
}
|
||||
|
||||
/* @end Index */
|
||||
|
||||
/* @group Student Robotics */
|
||||
|
||||
@btn-srobo-color: @gray-lighter;
|
||||
@btn-srobo-bg: #253571;
|
||||
@btn-srobo-border: darken(@btn-srobo-bg, 5%);
|
||||
.btn-srobo {
|
||||
.button-variant(@btn-srobo-color; @btn-srobo-bg; @btn-srobo-border);
|
||||
}
|
||||
|
||||
.thumbnail.sr-option {
|
||||
padding: 5px;
|
||||
& div.image {
|
||||
.image {
|
||||
background: url(../img/ninjas.png);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
height: 70vh;
|
||||
}
|
||||
.message {
|
||||
height: 15vh;
|
||||
color: white;
|
||||
background-color: #232323;
|
||||
text-align: center;
|
||||
}
|
||||
.move-on {
|
||||
text-align: center;
|
||||
background-color: #333;
|
||||
color: white;
|
||||
height: 5vh;
|
||||
}
|
||||
}
|
||||
/* @end 404 */
|
||||
|
||||
/* @group no-js */
|
||||
.no-js {
|
||||
.header {
|
||||
background-color: #232323;
|
||||
color: white;
|
||||
}
|
||||
#ie-scare {
|
||||
height: 150px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
/* @end no-js*/
|
||||
|
||||
/* @group content base */
|
||||
.jumbotron.header {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 15px;
|
||||
background-color: @body-bg;
|
||||
@media (max-width: @screen-xs-max) {
|
||||
padding-top: 50px;
|
||||
}
|
||||
h1 {
|
||||
margin: 10px 0;
|
||||
display: inline-block;
|
||||
font-size: 60px;
|
||||
}
|
||||
.image {
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
margin: 0;
|
||||
height: 225px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
/* @end Student Robotics */
|
||||
|
||||
/* @group external */
|
||||
|
||||
.gist {
|
||||
width: 100%
|
||||
#breadcrumbs {
|
||||
text-align: right;
|
||||
.breadcrumb {
|
||||
background: transparent;
|
||||
font-size: @font-size-h4;
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
li::before {
|
||||
content: "/";
|
||||
padding: 0 3px;
|
||||
}
|
||||
a {
|
||||
.transition(color 0.4s);
|
||||
color: #333;
|
||||
&:hover {
|
||||
color: #ff7f00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* @end external*/
|
||||
/* @end content base */
|
||||
|
||||
.panel {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.row {
|
||||
width: initial;
|
||||
}
|
||||
|
||||
.gh-card iframe {
|
||||
.box-shadow(0px 4px 4px 3px rgba(0,0,0,0.6));
|
||||
}
|
||||
|
||||
/* @group X-Large */
|
||||
|
||||
@media (min-width: 1500px) {
|
||||
.container {
|
||||
width: 1400px + @grid-gutter-width;
|
||||
}
|
||||
}
|
||||
|
||||
/* @end X-Large */
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
//
|
||||
// Variables
|
||||
// --------------------------------------------------
|
||||
|
||||
//== Colors
|
||||
//
|
||||
//## Gray and brand colors for use across Bootstrap.
|
||||
|
||||
@gray-base: #000;
|
||||
@gray-darker: lighten(@gray-base, 13.5%);
|
||||
@gray-dark: lighten(@gray-base, 20%);
|
||||
|
@ -15,34 +7,18 @@
|
|||
@brand-primary: #ff7f00;
|
||||
@brand-success: #5cb85c;
|
||||
@brand-info: #5bc0de;
|
||||
@brand-warning: #ebd300;
|
||||
@brand-warning: #f0ad4e;
|
||||
@brand-danger: #d9534f;
|
||||
|
||||
//== Scaffolding
|
||||
//
|
||||
//## Settings for some of the most global styles.
|
||||
|
||||
//** Background color for `<body>`.
|
||||
@body-bg: #232323;
|
||||
//** Global text color on `<body>`.
|
||||
@text-color: @gray-lighter;
|
||||
//** Global textual link color.
|
||||
@body-bg: #fff;
|
||||
@text-color: @gray-dark;
|
||||
@link-color: @brand-primary;
|
||||
//** Link hover color set via `darken()` function.
|
||||
@link-hover-color: darken(@link-color, 15%);
|
||||
//** Link hover decoration.
|
||||
@link-hover-decoration: underline;
|
||||
|
||||
//== Typography
|
||||
//
|
||||
//## Font, line-height, and color for body text, headings, and more.
|
||||
|
||||
@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
@font-family-serif: Georgia, "Times New Roman", Times, serif;
|
||||
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
|
||||
@font-family-sans-serif: 'Roboto', sans-serif;
|
||||
@font-family-serif: 'Roboto';
|
||||
@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
@font-family-base: @font-family-sans-serif;
|
||||
@font-size-base: 14px;
|
||||
@font-size-base: 18px;
|
||||
@font-size-large: ceil((@font-size-base * 1.25));
|
||||
@font-size-small: ceil((@font-size-base * 0.85));
|
||||
@font-size-h1: floor((@font-size-base * 2.6));
|
||||
|
@ -51,31 +27,15 @@
|
|||
@font-size-h4: ceil((@font-size-base * 1.25));
|
||||
@font-size-h5: @font-size-base;
|
||||
@font-size-h6: ceil((@font-size-base * 0.85));
|
||||
//** Unit-less `line-height` for use in components like buttons.
|
||||
@line-height-base: 1.428571429;
|
||||
//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
|
||||
@line-height-computed: floor((@font-size-base * @line-height-base));
|
||||
//** By default, this inherits from the `<body>`.
|
||||
@headings-font-family: inherit;
|
||||
@headings-font-weight: 500;
|
||||
@headings-font-weight: 300;
|
||||
@headings-line-height: 1.1;
|
||||
@headings-color: inherit;
|
||||
|
||||
//== Iconography
|
||||
//
|
||||
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
|
||||
|
||||
//** Load fonts from this directory.
|
||||
@icon-font-path: "../fonts/";
|
||||
//** File name for all font files.
|
||||
@icon-font-name: "glyphicons-halflings-regular";
|
||||
//** Element ID within SVG icon file.
|
||||
@icon-font-svg-id: "glyphicons_halflingsregular";
|
||||
|
||||
//== Components
|
||||
//
|
||||
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
|
||||
|
||||
@padding-base-vertical: 6px;
|
||||
@padding-base-horizontal: 12px;
|
||||
@padding-large-vertical: 10px;
|
||||
|
@ -89,42 +49,22 @@
|
|||
@border-radius-base: 4px;
|
||||
@border-radius-large: 6px;
|
||||
@border-radius-small: 3px;
|
||||
//** Global color for active items (e.g., navs or dropdowns).
|
||||
@component-active-color: #fff;
|
||||
//** Global background color for active items (e.g., navs or dropdowns).
|
||||
@component-active-bg: @brand-primary;
|
||||
//** Width of the `border` for generating carets that indicator dropdowns.
|
||||
@caret-width-base: 4px;
|
||||
//** Carets increase slightly in size for larger components.
|
||||
@caret-width-large: 5px;
|
||||
|
||||
//== Tables
|
||||
//
|
||||
//## Customizes the `.table` component with basic values, each used across all table variations.
|
||||
|
||||
//** Padding for `<th>`s and `<td>`s.
|
||||
@table-cell-padding: 8px;
|
||||
//** Padding for cells in `.table-condensed`.
|
||||
@table-condensed-cell-padding: 5px;
|
||||
//** Default background color used for all tables.
|
||||
@table-bg: transparent;
|
||||
//** Background color used for `.table-striped`.
|
||||
@table-bg-accent: @gray-light;
|
||||
//** Background color used for `.table-hover`.
|
||||
@table-bg-accent: #f9f9f9;
|
||||
@table-bg-hover: #f5f5f5;
|
||||
@table-bg-active: @table-bg-hover;
|
||||
//** Border color for table and cell borders.
|
||||
@table-border-color: #ddd;
|
||||
|
||||
//== Buttons
|
||||
//
|
||||
//## For each of Bootstrap's buttons, define text, background and border color.
|
||||
|
||||
@btn-font-weight: normal;
|
||||
@btn-default-color: #333;
|
||||
@btn-default-bg: #fff;
|
||||
@btn-default-border: #ccc;
|
||||
@btn-primary-color: @gray-darker;
|
||||
@btn-primary-color: #fff;
|
||||
@btn-primary-bg: @brand-primary;
|
||||
@btn-primary-border: darken(@btn-primary-bg, 5%);
|
||||
@btn-success-color: #fff;
|
||||
|
@ -133,80 +73,42 @@
|
|||
@btn-info-color: #fff;
|
||||
@btn-info-bg: @brand-info;
|
||||
@btn-info-border: darken(@btn-info-bg, 5%);
|
||||
@btn-warning-color: @gray-base;
|
||||
@btn-warning-color: #fff;
|
||||
@btn-warning-bg: @brand-warning;
|
||||
@btn-warning-border: darken(@btn-warning-bg, 5%);
|
||||
@btn-danger-color: #fff;
|
||||
@btn-danger-bg: @brand-danger;
|
||||
@btn-danger-border: darken(@btn-danger-bg, 5%);
|
||||
@btn-link-disabled-color: @gray-light;
|
||||
|
||||
//== Forms
|
||||
//
|
||||
//##
|
||||
|
||||
//** `<input>` background color
|
||||
@input-bg: #fff;
|
||||
//** `<input disabled>` background color
|
||||
@input-bg-disabled: @gray-lighter;
|
||||
//** Text color for `<input>`s
|
||||
@input-color: @gray;
|
||||
//** `<input>` border color
|
||||
@input-border: #ccc;
|
||||
//** Default `.form-control` border radius
|
||||
@input-border-radius: @border-radius-base;
|
||||
//** Large `.form-control` border radius
|
||||
@input-border-radius-large: @border-radius-large;
|
||||
//** Small `.form-control` border radius
|
||||
@input-border-radius-small: @border-radius-small;
|
||||
//** Border color for inputs on focus
|
||||
@input-border-focus: @brand-primary;
|
||||
//** Placeholder text color
|
||||
@input-border-focus: #66afe9;
|
||||
@input-color-placeholder: #999;
|
||||
//** Default `.form-control` height
|
||||
@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);
|
||||
//** Large `.form-control` height
|
||||
@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
|
||||
//** Small `.form-control` height
|
||||
@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
|
||||
//** `.form-group` margin
|
||||
@form-group-margin-bottom: 15px;
|
||||
@legend-color: @gray-dark;
|
||||
@legend-border-color: #e5e5e5;
|
||||
//** Background color for textual input addons
|
||||
@input-group-addon-bg: @gray-lighter;
|
||||
//** Border color for textual input addons
|
||||
@input-group-addon-border-color: @input-border;
|
||||
//** Disabled cursor for form controls and buttons.
|
||||
@cursor-disabled: not-allowed;
|
||||
|
||||
//== Dropdowns
|
||||
//
|
||||
//## Dropdown menu container and contents.
|
||||
|
||||
//** Background for the dropdown menu.
|
||||
@dropdown-bg: #fff;
|
||||
//** Dropdown menu `border-color`.
|
||||
@dropdown-border: rgba(0,0,0,.15);
|
||||
//** Dropdown menu `border-color` **for IE8**.
|
||||
@dropdown-fallback-border: #ccc;
|
||||
//** Divider color for between dropdown items.
|
||||
@dropdown-divider-bg: #e5e5e5;
|
||||
//** Dropdown link text color.
|
||||
@dropdown-link-color: @gray-dark;
|
||||
//** Hover color for dropdown links.
|
||||
@dropdown-link-hover-color: @dropdown-bg;
|
||||
//** Hover background for dropdown links.
|
||||
@dropdown-link-hover-bg: @dropdown-link-color;
|
||||
//** Active dropdown menu item text color.
|
||||
@dropdown-link-hover-color: #fff;
|
||||
@dropdown-link-hover-bg: darken(@gray-dark, 30%);
|
||||
@dropdown-link-active-color: @component-active-color;
|
||||
//** Active dropdown menu item background color.
|
||||
@dropdown-link-active-bg: @component-active-bg;
|
||||
//** Disabled dropdown menu item background color.
|
||||
@dropdown-link-disabled-color: @gray-light;
|
||||
//** Text color for headers within dropdown menus.
|
||||
@dropdown-header-color: @gray-light;
|
||||
//** Deprecated `@dropdown-caret-color` as of v3.1.0
|
||||
@dropdown-caret-color: #000;
|
||||
@zindex-navbar: 1000;
|
||||
@zindex-dropdown: 1000;
|
||||
|
@ -215,67 +117,31 @@
|
|||
@zindex-navbar-fixed: 1030;
|
||||
@zindex-modal-background: 1040;
|
||||
@zindex-modal: 1050;
|
||||
|
||||
//== Media queries breakpoints
|
||||
//
|
||||
//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
|
||||
|
||||
//** Deprecated `@screen-xs` as of v3.0.1
|
||||
@screen-xs: 480px;
|
||||
//** Deprecated `@screen-xs-min` as of v3.2.0
|
||||
@screen-xs-min: @screen-xs;
|
||||
//** Deprecated `@screen-phone` as of v3.0.1
|
||||
@screen-phone: @screen-xs-min;
|
||||
//** Deprecated `@screen-sm` as of v3.0.1
|
||||
@screen-sm: 862px;
|
||||
@screen-sm: 768px;
|
||||
@screen-sm-min: @screen-sm;
|
||||
//** Deprecated `@screen-tablet` as of v3.0.1
|
||||
@screen-tablet: @screen-sm-min;
|
||||
//** Deprecated `@screen-md` as of v3.0.1
|
||||
@screen-md: 1080px;
|
||||
@screen-md: 992px;
|
||||
@screen-md-min: @screen-md;
|
||||
//** Deprecated `@screen-desktop` as of v3.0.1
|
||||
@screen-desktop: @screen-md-min;
|
||||
//** Deprecated `@screen-lg` as of v3.0.1
|
||||
@screen-lg: 1200px;
|
||||
@screen-lg-min: @screen-lg;
|
||||
//** Deprecated `@screen-lg-desktop` as of v3.0.1
|
||||
@screen-lg-desktop: @screen-lg-min;
|
||||
@screen-xs-max: (@screen-sm-min - 1);
|
||||
@screen-sm-max: (@screen-md-min - 1);
|
||||
@screen-md-max: (@screen-lg-min - 1);
|
||||
|
||||
//== Grid system
|
||||
//
|
||||
//## Define your custom responsive grid.
|
||||
|
||||
//** Number of columns in the grid.
|
||||
@grid-columns: 12;
|
||||
//** Padding between columns. Gets divided in half for the left and right.
|
||||
@grid-gutter-width: 30px;
|
||||
//** Point at which the navbar becomes uncollapsed.
|
||||
@grid-float-breakpoint: @screen-sm-min;
|
||||
//** Point at which the navbar begins collapsing.
|
||||
@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
|
||||
|
||||
//== Container sizes
|
||||
//
|
||||
//## Define the maximum width of `.container` for different screen sizes.
|
||||
|
||||
@container-tablet: (660px + @grid-gutter-width);
|
||||
//** For `@screen-sm-min` and up.
|
||||
@container-tablet: (720px + @grid-gutter-width);
|
||||
@container-sm: @container-tablet;
|
||||
@container-desktop: (880px + @grid-gutter-width);
|
||||
//** For `@screen-md-min` and up.
|
||||
@container-desktop: (940px + @grid-gutter-width);
|
||||
@container-md: @container-desktop;
|
||||
@container-large-desktop: (1080px + @grid-gutter-width);
|
||||
//** For `@screen-lg-min` and up.
|
||||
@container-large-desktop: (1140px + @grid-gutter-width);
|
||||
@container-lg: @container-large-desktop;
|
||||
|
||||
//== Navbar
|
||||
//
|
||||
//##
|
||||
|
||||
@navbar-height: 50px;
|
||||
@navbar-margin-bottom: @line-height-computed;
|
||||
@navbar-border-radius: @border-radius-base;
|
||||
|
@ -314,21 +180,11 @@
|
|||
@navbar-inverse-toggle-hover-bg: #333;
|
||||
@navbar-inverse-toggle-icon-bar-bg: #fff;
|
||||
@navbar-inverse-toggle-border-color: #333;
|
||||
|
||||
//== Navs
|
||||
//
|
||||
//##
|
||||
|
||||
//=== Shared nav styles
|
||||
@nav-link-padding: 10px 15px;
|
||||
@nav-link-hover-bg: @gray-lighter;
|
||||
@nav-disabled-link-color: @gray-light;
|
||||
@nav-disabled-link-hover-color: @gray-light;
|
||||
|
||||
//== Tabs
|
||||
//
|
||||
//##
|
||||
|
||||
@nav-tabs-border-color: #ddd;
|
||||
@nav-tabs-link-hover-border-color: @gray-lighter;
|
||||
@nav-tabs-active-link-hover-bg: @body-bg;
|
||||
|
@ -336,19 +192,9 @@
|
|||
@nav-tabs-active-link-hover-border-color: #ddd;
|
||||
@nav-tabs-justified-link-border-color: #ddd;
|
||||
@nav-tabs-justified-active-link-border-color: @body-bg;
|
||||
|
||||
//== Pills
|
||||
//
|
||||
//##
|
||||
|
||||
@nav-pills-border-radius: @border-radius-base;
|
||||
@nav-pills-active-link-hover-bg: @component-active-bg;
|
||||
@nav-pills-active-link-hover-color: @component-active-color;
|
||||
|
||||
//== Pagination
|
||||
//
|
||||
//##
|
||||
|
||||
@pagination-color: @link-color;
|
||||
@pagination-bg: #fff;
|
||||
@pagination-border: #ddd;
|
||||
|
@ -361,11 +207,6 @@
|
|||
@pagination-disabled-color: @gray-light;
|
||||
@pagination-disabled-bg: #fff;
|
||||
@pagination-disabled-border: #ddd;
|
||||
|
||||
//== Pager
|
||||
//
|
||||
//##
|
||||
|
||||
@pager-bg: @pagination-bg;
|
||||
@pager-border: @pagination-border;
|
||||
@pager-border-radius: 15px;
|
||||
|
@ -373,21 +214,11 @@
|
|||
@pager-active-bg: @pagination-active-bg;
|
||||
@pager-active-color: @pagination-active-color;
|
||||
@pager-disabled-color: @pagination-disabled-color;
|
||||
|
||||
//== Jumbotron
|
||||
//
|
||||
//##
|
||||
|
||||
@jumbotron-padding: 30px;
|
||||
@jumbotron-color: @gray-dark;
|
||||
@jumbotron-bg: #fff;
|
||||
@jumbotron-color: inherit;
|
||||
@jumbotron-bg: @gray-lighter;
|
||||
@jumbotron-heading-color: inherit;
|
||||
@jumbotron-font-size: ceil((@font-size-base * 1.5));
|
||||
|
||||
//== Form states and alerts
|
||||
//
|
||||
//## Define colors for form feedback states and, by default, alerts.
|
||||
|
||||
@state-success-text: #3c763d;
|
||||
@state-success-bg: #dff0d8;
|
||||
@state-success-border: darken(spin(@state-success-bg, -10), 5%);
|
||||
|
@ -400,101 +231,43 @@
|
|||
@state-danger-text: #a94442;
|
||||
@state-danger-bg: #f2dede;
|
||||
@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);
|
||||
|
||||
//== Tooltips
|
||||
//
|
||||
//##
|
||||
|
||||
//** Tooltip max width
|
||||
@tooltip-max-width: 200px;
|
||||
//** Tooltip text color
|
||||
@tooltip-color: #fff;
|
||||
//** Tooltip background color
|
||||
@tooltip-bg: #000;
|
||||
@tooltip-opacity: .9;
|
||||
//** Tooltip arrow width
|
||||
@tooltip-arrow-width: 5px;
|
||||
//** Tooltip arrow color
|
||||
@tooltip-arrow-color: @tooltip-bg;
|
||||
|
||||
//== Popovers
|
||||
//
|
||||
//##
|
||||
|
||||
//** Popover body background color
|
||||
@popover-bg: #fff;
|
||||
//** Popover maximum width
|
||||
@popover-max-width: 276px;
|
||||
//** Popover border color
|
||||
@popover-border-color: rgba(0,0,0,.2);
|
||||
//** Popover fallback border color
|
||||
@popover-fallback-border-color: #ccc;
|
||||
//** Popover title background color
|
||||
@popover-title-bg: darken(@popover-bg, 3%);
|
||||
//** Popover arrow width
|
||||
@popover-arrow-width: 10px;
|
||||
//** Popover arrow color
|
||||
@popover-arrow-color: @popover-bg;
|
||||
//** Popover outer arrow width
|
||||
@popover-arrow-outer-width: (@popover-arrow-width + 1);
|
||||
//** Popover outer arrow color
|
||||
@popover-arrow-outer-color: fadein(@popover-border-color, 5%);
|
||||
//** Popover outer arrow fallback color
|
||||
@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);
|
||||
|
||||
//== Labels
|
||||
//
|
||||
//##
|
||||
|
||||
//** Default label background color
|
||||
@label-default-bg: @gray-light;
|
||||
//** Primary label background color
|
||||
@label-primary-bg: @brand-primary;
|
||||
//** Success label background color
|
||||
@label-success-bg: @brand-success;
|
||||
//** Info label background color
|
||||
@label-info-bg: @brand-info;
|
||||
//** Warning label background color
|
||||
@label-warning-bg: @brand-warning;
|
||||
//** Danger label background color
|
||||
@label-danger-bg: @brand-danger;
|
||||
//** Default label text color
|
||||
@label-color: #fff;
|
||||
//** Default text color of a linked label
|
||||
@label-link-hover-color: #fff;
|
||||
|
||||
//== Modals
|
||||
//
|
||||
//##
|
||||
|
||||
//** Padding applied to the modal body
|
||||
@modal-inner-padding: 15px;
|
||||
//** Padding applied to the modal title
|
||||
@modal-title-padding: 15px;
|
||||
//** Modal title line-height
|
||||
@modal-title-line-height: @line-height-base;
|
||||
//** Background color of modal content area
|
||||
@modal-content-bg: #fff;
|
||||
//** Modal content border color
|
||||
@modal-content-border-color: rgba(0,0,0,.2);
|
||||
//** Modal content border color **for IE8**
|
||||
@modal-content-fallback-border-color: #999;
|
||||
//** Modal backdrop background color
|
||||
@modal-backdrop-bg: #000;
|
||||
//** Modal backdrop opacity
|
||||
@modal-backdrop-opacity: .5;
|
||||
//** Modal header border color
|
||||
@modal-header-border-color: #e5e5e5;
|
||||
//** Modal footer border color
|
||||
@modal-footer-border-color: @modal-header-border-color;
|
||||
@modal-lg: 900px;
|
||||
@modal-md: 600px;
|
||||
@modal-sm: 300px;
|
||||
|
||||
//== Alerts
|
||||
//
|
||||
//## Define alert colors, border radius, and padding.
|
||||
|
||||
@alert-padding: 15px;
|
||||
@alert-border-radius: @border-radius-base;
|
||||
@alert-link-font-weight: bold;
|
||||
|
@ -510,68 +283,33 @@
|
|||
@alert-danger-bg: @state-danger-bg;
|
||||
@alert-danger-text: @state-danger-text;
|
||||
@alert-danger-border: @state-danger-border;
|
||||
|
||||
//== Progress bars
|
||||
//
|
||||
//##
|
||||
|
||||
//** Background color of the whole progress component
|
||||
@progress-bg: #f5f5f5;
|
||||
//** Progress bar text color
|
||||
@progress-bar-color: #fff;
|
||||
//** Variable for setting rounded corners on progress bar.
|
||||
@progress-border-radius: @border-radius-base;
|
||||
//** Default progress bar color
|
||||
@progress-bar-bg: @brand-primary;
|
||||
//** Success progress bar color
|
||||
@progress-bar-success-bg: @brand-success;
|
||||
//** Warning progress bar color
|
||||
@progress-bar-warning-bg: @brand-warning;
|
||||
//** Danger progress bar color
|
||||
@progress-bar-danger-bg: @brand-danger;
|
||||
//** Info progress bar color
|
||||
@progress-bar-info-bg: @brand-info;
|
||||
|
||||
//== List group
|
||||
//
|
||||
//##
|
||||
|
||||
//** Background color on `.list-group-item`
|
||||
@list-group-bg: #fff;
|
||||
//** `.list-group-item` border color
|
||||
@list-group-border: #ddd;
|
||||
//** List group border radius
|
||||
@list-group-border-radius: @border-radius-base;
|
||||
//** Background color of single list items on hover
|
||||
@list-group-hover-bg: #f5f5f5;
|
||||
//** Text color of active list items
|
||||
@list-group-active-color: @component-active-color;
|
||||
//** Background color of active list items
|
||||
@list-group-active-bg: @component-active-bg;
|
||||
//** Border color of active list elements
|
||||
@list-group-active-border: @list-group-active-bg;
|
||||
//** Text color for content within active list items
|
||||
@list-group-active-text-color: lighten(@list-group-active-bg, 40%);
|
||||
//** Text color of disabled list items
|
||||
@list-group-disabled-color: @gray-light;
|
||||
//** Background color of disabled list items
|
||||
@list-group-disabled-bg: @gray-lighter;
|
||||
//** Text color for content within disabled list items
|
||||
@list-group-disabled-text-color: @list-group-disabled-color;
|
||||
@list-group-link-color: #555;
|
||||
@list-group-link-hover-color: @list-group-link-color;
|
||||
@list-group-link-heading-color: #333;
|
||||
|
||||
//== Panels
|
||||
//
|
||||
//##
|
||||
|
||||
@panel-bg: #fff;
|
||||
@panel-body-padding: 15px;
|
||||
@panel-heading-padding: 10px 15px;
|
||||
@panel-footer-padding: @panel-heading-padding;
|
||||
@panel-border-radius: @border-radius-base;
|
||||
//** Border color for elements within panels
|
||||
@panel-inner-border: #ddd;
|
||||
@panel-footer-bg: #f5f5f5;
|
||||
@panel-default-text: @gray-dark;
|
||||
|
@ -592,66 +330,28 @@
|
|||
@panel-danger-text: @state-danger-text;
|
||||
@panel-danger-border: @state-danger-border;
|
||||
@panel-danger-heading-bg: @state-danger-bg;
|
||||
|
||||
//== Thumbnails
|
||||
//
|
||||
//##
|
||||
|
||||
//** Padding around the thumbnail image
|
||||
@thumbnail-padding: 5px;
|
||||
//** Thumbnail background color
|
||||
@thumbnail-bg: @gray-darker;
|
||||
//** Thumbnail border color
|
||||
@thumbnail-border: #999;
|
||||
//** Thumbnail border radius
|
||||
@thumbnail-padding: 4px;
|
||||
@thumbnail-bg: @body-bg;
|
||||
@thumbnail-border: #ddd;
|
||||
@thumbnail-border-radius: @border-radius-base;
|
||||
//** Custom text color for thumbnail captions
|
||||
@thumbnail-caption-color: #fff;
|
||||
//** Padding around the thumbnail caption
|
||||
@thumbnail-caption-padding: 7px;
|
||||
|
||||
//== Wells
|
||||
//
|
||||
//##
|
||||
|
||||
@well-bg: @jumbotron-bg;
|
||||
@thumbnail-caption-color: @text-color;
|
||||
@thumbnail-caption-padding: 9px;
|
||||
@well-bg: #f5f5f5;
|
||||
@well-border: darken(@well-bg, 7%);
|
||||
|
||||
//== Badges
|
||||
//
|
||||
//##
|
||||
|
||||
@badge-color: #fff;
|
||||
//** Linked badge text color on hover
|
||||
@badge-link-hover-color: #fff;
|
||||
@badge-bg: @gray-light;
|
||||
//** Badge text color in active nav link
|
||||
@badge-active-color: @link-color;
|
||||
//** Badge background color in active nav link
|
||||
@badge-active-bg: #fff;
|
||||
@badge-font-weight: bold;
|
||||
@badge-line-height: 1;
|
||||
@badge-border-radius: 10px;
|
||||
|
||||
//== Breadcrumbs
|
||||
//
|
||||
//##
|
||||
|
||||
@breadcrumb-padding-vertical: 8px;
|
||||
@breadcrumb-padding-horizontal: 15px;
|
||||
//** Breadcrumb background color
|
||||
@breadcrumb-bg: #f5f5f5;
|
||||
//** Breadcrumb text color
|
||||
@breadcrumb-color: #ccc;
|
||||
//** Text color of current page in the breadcrumb
|
||||
@breadcrumb-active-color: @gray-light;
|
||||
//** Textual separator for between breadcrumb elements
|
||||
@breadcrumb-separator: "/";
|
||||
|
||||
//== Carousel
|
||||
//
|
||||
//##
|
||||
|
||||
@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
|
||||
@carousel-control-color: #fff;
|
||||
@carousel-control-width: 15%;
|
||||
|
@ -660,19 +360,9 @@
|
|||
@carousel-indicator-active-bg: #fff;
|
||||
@carousel-indicator-border-color: #fff;
|
||||
@carousel-caption-color: #fff;
|
||||
|
||||
//== Close
|
||||
//
|
||||
//##
|
||||
|
||||
@close-font-weight: bold;
|
||||
@close-color: #000;
|
||||
@close-text-shadow: 0 1px 0 #fff;
|
||||
|
||||
//== Code
|
||||
//
|
||||
//##
|
||||
|
||||
@code-color: #c7254e;
|
||||
@code-bg: #f9f2f4;
|
||||
@kbd-color: #fff;
|
||||
|
@ -681,28 +371,13 @@
|
|||
@pre-color: @gray-dark;
|
||||
@pre-border-color: #ccc;
|
||||
@pre-scrollable-max-height: 340px;
|
||||
|
||||
//== Type
|
||||
//
|
||||
//##
|
||||
|
||||
//** Horizontal offset for forms and lists.
|
||||
@component-offset-horizontal: 180px;
|
||||
//** Text muted color
|
||||
@text-muted: @gray-light;
|
||||
//** Abbreviations and acronyms border color
|
||||
@abbr-border-color: @gray-light;
|
||||
//** Headings small color
|
||||
@headings-small-color: @gray-light;
|
||||
//** Blockquote small color
|
||||
@blockquote-small-color: @gray-light;
|
||||
//** Blockquote font size
|
||||
@blockquote-font-size: (@font-size-base * 1.25);
|
||||
//** Blockquote border color
|
||||
@blockquote-border-color: @gray-lighter;
|
||||
//** Page header border color
|
||||
@page-header-border-color: @gray-lighter;
|
||||
//** Width of horizontal description list titles
|
||||
@dl-horizontal-offset: @component-offset-horizontal;
|
||||
//** Horizontal line color.
|
||||
@hr-border: @gray-lighter;
|
||||
|
|
|
@ -1,49 +1,41 @@
|
|||
{% extends 'base.html' %}
|
||||
{% extends 'content_base.html' %}
|
||||
{% block pageTitle %}About all the things{% endblock %}
|
||||
|
||||
{% block htmltitle %}About{% endblock %}
|
||||
|
||||
{% block headercontent %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<h1>About all the things</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h4>So, who and/or what am I exactly? Let's find out...</h4>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content%}
|
||||
<div class="container">
|
||||
<p>
|
||||
There are 2 parts to this, me and my website. Information for both of which is below.
|
||||
</p>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row center-text">
|
||||
<div class="col-sm-6">
|
||||
<div class="thumbnail panel-primary">
|
||||
<p class="center-text mega-icon">
|
||||
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
|
||||
<div class="col-sm-6">
|
||||
<div class="thumbnail">
|
||||
<p class="center-text mega-icon">
|
||||
<span class="glyphicon glyphicon-hdd" aria-hidden="true"></span>
|
||||
</p>
|
||||
<div class="caption">
|
||||
<h3>About Website</h3>
|
||||
<p>
|
||||
Some info about my website, which clearly works well as you're using it right now!
|
||||
</p>
|
||||
<p>
|
||||
<a href="/about/website/" class="btn btn-primary btn-block">More Info</a>
|
||||
</p>
|
||||
<div class="caption">
|
||||
<h3>About Me</h3>
|
||||
<p></p>
|
||||
<p><a href="#" class="btn btn-primary btn-block btn-lg" role="button">Find out more</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="thumbnail panel-primary">
|
||||
<p class="center-text mega-icon">
|
||||
<span class="glyphicon glyphicon-hdd" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="thumbnail">
|
||||
<p class="center-text mega-icon">
|
||||
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
|
||||
</p>
|
||||
<div class="caption">
|
||||
<h3>About Me</h3>
|
||||
<p>
|
||||
Some info about me. Although not very much. Because Privacy!
|
||||
</p>
|
||||
<p>
|
||||
<a href="/about/me/" class="btn btn-primary btn-block">More Info</a>
|
||||
</p>
|
||||
<div class="caption">
|
||||
<h3>About the website</h3>
|
||||
<p></p>
|
||||
<p><a href="#" class="btn btn-primary btn-block btn-lg" role="button">Find out more</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
19
templates/about/me.html
Normal file
19
templates/about/me.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends 'content_base.html' %}
|
||||
|
||||
{% block pageTitle %}About Me{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<p>Stuff</p>
|
||||
</div>
|
||||
<div class="col-sm-4 gh-card">
|
||||
<div data-theme="medium" data-github="RealOrangeOne" class="github-card"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script async defer src="//cdn.jsdelivr.net/github-cards/latest/widget.js"></script>
|
||||
{% endblock %}
|
|
@ -1,54 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block htmltitle %}About the website{% endblock %}
|
||||
|
||||
{% block headercontent %}
|
||||
<div class="row">
|
||||
<h1>The Website</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h4>Well it's obvious it works pretty damn well, you're looking at it right now!</h4>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content%}
|
||||
<div class="container">
|
||||
<p>
|
||||
My website is the culmination of all my knowledge, compiled into 1 place. It not only contains all my projects, but it in itself is a project. Making sure this website works properly is a tall order, especially considering it's self hosted. And making sure that it stays secure is also important, as it contains a large amount of personal information.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<img style="border-radius: 12px;" class="full-width" src="" />
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<h3>The server</h3>
|
||||
<p>
|
||||
The server itself is a VPS hosted by Inception hosting. Obviously if I did more looking around I could probably find a slightly better deal, but these people have brilliant customer support, fast and customizable servers, that are also hosted in a data center in the UK (a major bonus)!
|
||||
</p>
|
||||
<p>
|
||||
The spec on this server are nothing special, but considering it wouldn't be running much, other than a web server, and a couple of other applications, it's pleanty. The most important thing is that it is hosted in the UK, for connection speed, and for other applications like a VPN.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<img style="border-radius: 12px;" class="full-width" src="" />
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<h3>The website</h3>
|
||||
<p>
|
||||
The website itself is written in python, using Django, and a PostgreSQL database. Now obviously for what I need this is massivly overkill, but it means I can use the skills and shortcuts I learn at work to make a very fast and good looking website. It also means that if I ever want to expand and add new features, then with python running the back end, it's going to be very easy!
|
||||
</p>
|
||||
<p>
|
||||
I went with the Django framework because it's what I work with at work, so I have a lot of contact with it, so exposure to bugs or clean ways to write things happen on a daily basis. I also chose it because it's written in python, one of my favourite languages, and one i'm highly fluent in. I chose PostgreSQL as a database engine because it's again what we use at work, and I already had some files preconfigured with the required config.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
14
templates/about/website.md
Normal file
14
templates/about/website.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# About my website
|
||||
My website is the culmination of all my knowledge, compiled into 1 place. It not only contains all my projects, but it in itself is a project. Making sure this website works properly is a tall order, especially considering it's self hosted.
|
||||
|
||||
## The Website
|
||||
The website itself is written in python, using the Django framework, and a SQLite database. For what I need it's more than overkill, but hey, why not!
|
||||
|
||||
I went with the Django framework because it's what I use with at work, as well as the fact it's simple, clean and easy. It also allows for some server side assets, eg blogging.
|
||||
|
||||
The only reason I have a database is because certain sections require it. For this reason I went with SQLite, because it's really lightweight and simple.
|
||||
|
||||
## The server
|
||||
The website is hosted on my UK VPS. Previous versions have been hosted on 1&1 and MyWindowsHosting.
|
||||
|
||||
The Django application itself is served using waitress. This get's it's port from a custom reverse proxy allowing me to host multiple sites on a single server easily. This is the same one I use for local development. The main web-facing server is nginx, because it's simple to setup, and damn fast!
|
|
@ -2,151 +2,62 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{% block htmltitle %}{% endblock %} | TheOrangeOne</title>
|
||||
<title>{{ html_title }} | TheOrangeOne</title>
|
||||
<meta chatset='utf-8' />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
<script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}"/>
|
||||
<link rel="shortcut icon" href=""/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="row page-width page-height" id="header" {% if header_BG %}style="background-image: url('{{ header_BG }}');" {% endif %}>
|
||||
<div class="col-sm-10 col-sm-offset-1 jumbotron container">
|
||||
{% block headercontent %}{% endblock %}
|
||||
<body class="{{ body_class }}">
|
||||
<div class="content-wrapper">
|
||||
{% block baseContent%}{% endblock %}
|
||||
</div>
|
||||
<div class="row page-width" id="page-down">
|
||||
<div class="col-md-2 col-md-offset-5">
|
||||
<i class="icon ion-chevron-down h2 clickable" id="page-down-button"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id='navbar-anchor'></div>
|
||||
<div id="navbar-container" class="align h4" style="width: 96%; left: 2%; margin: 0; z-index: 10000;">
|
||||
<nav class="navbar navbar-inverse" style="border-radius: 0;">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand visible-xs"><i class="icon ion-compass"></i> Navigation</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar" style=" padding-left: 0px;">
|
||||
<ul class="nav navbar-nav home-button hidden-sm">
|
||||
<li class="active home"><a href="{% url 'pages:index' %}"><i class="icon ion-home"></i></a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav" id="navigation">
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Projects <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li><a href="#"><i class="icon ion-social-freebsd-devil"></i> Pithos</a></li>
|
||||
<li><a href="{% url 'projects:bsod-enabler'%}"><i class="icon ion-ios-monitor"></i> BSOD Enabler</a></li>
|
||||
<li><a href="{% url 'projects:hipchat-emoticons' %}"><i class="icon ion-chatbox-working"></i> Hipchat Emoticons for All</a></li>
|
||||
<li><a href="{% url 'setup:desk' %}"><i class="icon ion-social-windows"></i> Custom PC</a></li>
|
||||
<li><a href="{% url 'projects:index' %}"><i class="icon ion-android-more-vertical"></i> All Projects...</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Code <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li><a href="#"><i class="icon ion-code-working"></i> Code Challenges</a></li>
|
||||
<li><a href="{% url 'projects:morse-code-decoder' %}"><i class="icon ion-ios-circle-filled"></i> Morse Code Decoder</a></li>
|
||||
<li><a href="{% url 'projects:wiki-game-solver' %}"><i class="icon ion-ios-game-controller-a"></i> The Wiki Game Solver</a></li>
|
||||
<li><a href=""><span class="glyphicon glyphicon-print" aria-hidden="true"></span> Printr</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
College <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li><a href="{% url 'robotics:index' %}">Student Robotics</a></li>
|
||||
<li><a href="{% url 'projects:attack-on-blocks' %}"><i class="icon ion-cube"></i> Attack on Blocks Game</a></li>
|
||||
<li><a href="{% url 'college:student-server' %}"><span class="glyphicon glyphicon-console" aria-hidden="true"></span> Student Server</a></li>
|
||||
<li><a href="#"><i class="icon ion-ios-paper"></i> EPQ</a></li>
|
||||
<li><a href="#">Wall of Sheep</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Setup <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li><a href="{% url 'setup:desk' %}">💁 Desk</a></li>
|
||||
<li><a href="#"><i class="icon ion-briefcase"></i> Work</a></li>
|
||||
<li><a href="#"><i class="icon ion-model-s"></i> On the Go</a></li>
|
||||
<li><a href="#"><i class="icon ion-android-phone-portrait"></i> Devices</a></li>
|
||||
<li><a href="#"><span class="glyphicon glyphicon-console" aria-hidden="true"></span> Servers</a></li>
|
||||
<li><a href="{% url 'setup:index' %}"><i class="icon ion-android-more-vertical"></i> All</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Work <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li><a href="#"><i class="icon ion-fork-repo"></i> Projects</a></li>
|
||||
<li><a href="#"><i class="icon ion-android-desktop"></i> Setup</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Media <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li><a href="{% url 'media:youtube' %}"><i class="icon ion-social-youtube"></i> Youtube Channel</a></li>
|
||||
<li><a href="#"><i class="icon ion-social-rss"></i> Feed</a></li>
|
||||
<li><a href="{% url 'media:gallery' %}"><i class="icon ion-ios-camera"></i> Gallery</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">Links</a></li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
About <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li><a href="#"><i class="icon ion-android-person"></i> Me</a></li>
|
||||
<li><a href="{% url 'pages:about-website' %}"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> Website</a></li>
|
||||
<li><a href="#"><i class="icon ion-android-contacts"></i> Contact Me</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Account <i class="icon ion-ios-arrow-up navbar-icon h4"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropup">
|
||||
<li class="active hidden-xs"><a><i class="icon ion-ios-body-outline"></i> *username*</a></li>
|
||||
<li><a href="#"><i class="icon ion-ios-cog-outline"></i> Preferences</a></li>
|
||||
<li><a href="#"><i class="icon ion-log-in"></i> Login / Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p class="social">
|
||||
<a href="{{ links.twitter }}"><i class="icon ion-social-twitter"></i></a>
|
||||
<a href="{{ links.instagram }}"><i class="icon ion-social-instagram-outline"></i></a>
|
||||
<a href="{{ links.reddit }}"><i class="icon ion-social-reddit"></i></a>
|
||||
<a href="{{ links.youtube }}"><i class="icon ion-social-youtube"></i></a>
|
||||
<a href="soon"><i class="icon ion-social-codepen"></i></a>
|
||||
<a href="soon"><i class="icon ion-social-twitch-outline"></i></a>
|
||||
<a href="{{ links.github }}"><i class="icon ion-social-octocat"></i></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
{% block content %}{% endblock %}
|
||||
{% if not no_footer %}
|
||||
<footer>
|
||||
<p class="center-text">Copyright © Jake Howard 2015</p>
|
||||
<p class="center-text footer-links">
|
||||
<a href="{%url 'pages:about' %}">About</a> - <a href="">Contact</a> - <a href="">Things</a>
|
||||
</p>
|
||||
</footer>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p class="bar-links">
|
||||
<a href="/about/">About</a> |
|
||||
<a href="{{ links.github }}/theorangeone.net" target="_blank">View Source</a>
|
||||
<p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 powered-by">
|
||||
<p>Powered by <a href="https://www.djangoproject.com/">Django</a>, <a href="https://clients.inceptionhosting.com/aff.php?aff=256">Inception Hosting</a>, and a whole heap of <a href="https://github.com/RealOrangeOne/theorangeone.net">Magic</a>!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<a href="https://circleci.com/gh/RealOrangeOne/theorangeone.net" target="_blank">
|
||||
<img class="ci-badge" src="https://circleci.com/gh/RealOrangeOne/theorangeone.net.svg?style=svg"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script type="text/javascript" src="{% static 'js/libs.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/app.js' %}"></script>
|
||||
{% if js_redirect %}
|
||||
<noscript>
|
||||
<style> html, body { display:none; }</style>
|
||||
<meta http-equiv="refresh" content="0.0;url=/no-js">
|
||||
</noscript>
|
||||
{% endif %}
|
||||
<script type="text/javascript" src="{% static 'js/libs.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/utils.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/app.js' %}"></script>
|
||||
<noscript>
|
||||
<style> html, body { display:none; }</style>
|
||||
<meta http-equiv="refresh" content="0.0;url={% url 'pages:no-js' %}">
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
|
|
18
templates/blog/post.html
Normal file
18
templates/blog/post.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends 'content_base.html' %}
|
||||
|
||||
{% block pageTitle %}{{ html_title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-9">
|
||||
{{ blog.content | safe }}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<h5>Published: {{ blog.date }}</h5>
|
||||
<h5><i class="icon ion-thumbsup"></i> {{ blog.like_count }}</h5>
|
||||
<h5><a href="{{ blog.URL }}">View Post</a></h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,60 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load staticfiles %}
|
||||
{% block htmltitle %}Attack on Blocks{% endblock %}
|
||||
|
||||
{% block headercontent %}
|
||||
<div class="row">
|
||||
<h1>Attack on Blocks</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h4>It's like the classic game 'Space Invaders', just with better music, customizable texture packs, and a couple of easter eggs...</h4>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content%}
|
||||
<div class="container">
|
||||
<p>
|
||||
Attack on Blocks is a space invaders style game that I wrote for my IT coursework, for the games development unit. We were allowed to make any game that we wanted, provided it could be done within the time limits, be very easy to play, and easily run on the college computer (which were pretty terrible). I had never written a game before, so I knew this was going to be a challenge.</p>
|
||||
<p>
|
||||
I decided to write the game in Python, seeing as there were other people in the class that could help me bug report and test features, and because it was easy to run on the college computers. I used PyGame for the graphics library, even though I had never used it before, because it was really simple to use, and there was a lot of support and documentation online.
|
||||
</p>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h2>The Easter Eggs</h2>
|
||||
<p>
|
||||
One of the key features of this take on space invaders (and unfortunately the thing I spent the most time on), is the easter eggs. There are a few dotted around the game, which make the game either much easier, or way more fun! At the moment, there are 3 main easter eggs, the first enabling the other 2. If you would like to know what they are, click the button below. If not, pay the game and try and find them, or search through the source to find them (it's not too hard through the source).
|
||||
</p>
|
||||
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
|
||||
<div class="panel-primary">
|
||||
<div class="panel-heading" role="tab" id="headingOne">
|
||||
<h4 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
|
||||
See Easter Eggs...
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseOne" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
|
||||
<div class="panel-body panel black-text">
|
||||
<h4></h4>
|
||||
<p></p>
|
||||
<h4></h4>
|
||||
<p></p>
|
||||
<h4></h4>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
As you will see (If and when you find the easter eggs), most of them are completely useless, and completely unrelated to the game or anything else. The main reason they were put in was because i'm friends with people that pester to the point it's just easier to give in. Hence there are some really very odd ones!
|
||||
</p>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="btn-group btn-group-justified">
|
||||
<p class="center-text">
|
||||
<a class="btn btn-primary btn-lg" href="" download="Attack-on-blocks.zip">Download Attack on Blocks</a>
|
||||
<a class="btn btn-default btn-lg" href="https://github.com/RealOrangeOne/attack-on-blocks">View on Github <i class="icon ion-social-github"></i></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,40 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load staticfiles %}
|
||||
{% block htmltitle %}Student Server | College{% endblock %}
|
||||
|
||||
{% block headercontent %}
|
||||
<div class="row">
|
||||
<h1>Student Server</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h4>The first server I ever properly ran, and surprisingly it didn't really break, that much!</h4>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content%}
|
||||
<div class="container">
|
||||
<p>
|
||||
Back when I was in college, we needed a server for computing students to learn how to FTP, and script on a server using python CGI and <a href="Link to tonys php toolbox analagy">PHP</a>, as well as possibly for some students coursework. Fortunately, the college already had one, running the IT students microsite for extra course information. The problem was that it was majorly out of date, and no one really new how to use it properly. It was up to me and my friend Alex to bring the server up to date, and make it ready for the students who needed it.
|
||||
</p>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p>
|
||||
The original plan was to update the server's OS (at that stage running Ubuntu 12.04 LTS), install the python and PHP backends, add the users, and then make sure they couldn't edit eachothers documents. In the end Alex did a server backup, and then fully reinstalled the server OS from scratch, and then pushed the documents back on, which made our lives a lot easier.
|
||||
</p>
|
||||
<p>
|
||||
Because he had worked with servers a lot in the past, and was already very fluent with the ubuntu terminal, he installed the software that was needed, and got it all configured properly, whilst I worked on the student logins and permission structure.
|
||||
</p>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h3>User Creation</h3>
|
||||
<p>
|
||||
I knew we would need user accounts for the computing teachers, for the students doing A2 computing, and for updating the IT site, but I wasnt expecting this to amount to over 50 user accounts that needed to be created, and permissions setup for their accounts. It was then that I realied that I would need to write a script to do this in any useful amount of time. Fortunately Alex had started writing one with a small amount of logic, so I had something to work off to get this done, as this was my first major linux project.
|
||||
</p>
|
||||
<p>
|
||||
The basis of the script was to load information about the users from a database I had created with all the required students in, create users based on this information, and configure the permissions for their user and their home directory. The script also allowed for manual entering of users with the same permission template, in case single users needed to be created. An additional feature that I added which has proved useful now that i've left is the ability to delete users manually, and from that original database, to make sure that no student will have access to the server once they have left, well, other than me that is!
|
||||
</p>
|
||||
<p>
|
||||
The script I used to create these files can be found below, hosted as a gist on github. Unfortunately some of the information has been redacted to prevent giving too much information that could be considered a security threat to the server. The script may not work in this redacted state, however all the core logic has been kept.
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
15
templates/college/student-server.md
Normal file
15
templates/college/student-server.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Student Server
|
||||
Back when I was in college, we needed a server for computing students to learn how to use FTP, and script on a server using python CGI and [PHP](http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/#an-analogy), as well as possibly for some students coursework. Fortunately, the college already had one, running the IT students microsite for extra course information. The problem was that it was majorly out of date, and no one really new how to use it properly. It was up to me and my friend Alex to bring the server up to date, and get it ready for the students who needed it.
|
||||
|
||||
The original plan was to update the server's OS (at that stage running Ubuntu 12.04 LTS), install python and [PHP](http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/#an-analogy) backends, add student users, and then make sure they couldn't edit each others documents. In the end, because we had no idea how the server worked, because it was setup a long time ago, we decided it was just easier to backup what we needed, then do a complete fresh install. Meaning we could set things up exactly how we wanted them, and install the tools we needed.
|
||||
|
||||
## User Creation
|
||||
I knew we would need user accounts for all the computing teachers, the students doing A2 computing. I wasn't expecting this to amount to over 50 user accounts that needed to be created, and permissions setup for their accounts. Fortunately Alex had started writing a basic script for this, which I quickly modified.
|
||||
|
||||
The basis of the script was to load information about the users from a database I had created (by hand) with all the required students in, create users based on this information, and configure the permissions for the user and their home directory. The script also allowed for manual entering of users with the same permission template, in case single users needed to be created. An additional feature that I added which has proved useful now that I've left is the ability to delete users manually, and from that original database, to make sure that no student will have access to the server once they have left, well, other than me that is!
|
||||
|
||||
### The script
|
||||
Because a lot of the accounts are still active, and that new user accounts are being created in the same way the exact script cannot be shown, for security reasons.
|
||||
|
||||
## What next?
|
||||
Now that I've left college, I've passed on the server to other people, although I do still have an account. From what I hear, fewer students are using the server. However, they have made the microsite look infinitely better!
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue