lots of new pages and changes and start of membership system

This commit is contained in:
Oliver Marks 2015-12-10 13:52:58 +00:00
parent 5e90e70010
commit c101b17f37
154 changed files with 3353 additions and 198 deletions

View File

@ -11,7 +11,7 @@ RUN \
apt-get update && \
apt-get upgrade -y && \
apt-get install -y software-properties-common python-software-properties && \
apt-get install -y python-requests python-lxml python-flask python-tz
apt-get install -y python-requests python-lxml python-flask python-flask-login python-misaka python-tz python-mysqldb python-psycopg2 python-requests-oauthlib
RUN add-apt-repository -y ppa:oly/ppa
RUN apt-get update

View File

@ -24,3 +24,13 @@ Most of the content is generated statically to avoid hitting a database on each
To generate static content you can run the code below.
``` python generate.py ```
Run locally with uwsgi on port 9090
uwsgi --plugins python --http-socket :9090 -w wsgi
Run locally with flask
python index.py

View File

@ -3,3 +3,4 @@ lxml
requests
pytz
pip install -e bzr+lp:scaffold#egg=scaffold
python-requests-oauthlib

371
site/authorize.py Normal file
View File

@ -0,0 +1,371 @@
import os
import sys
import time
import uuid
import hashlib
import datetime
from werkzeug import secure_filename
from werkzeug.security import generate_password_hash, check_password_hash
from flask import Flask, session, flash, get_flashed_messages
from flask import redirect, abort
from flask import make_response
from flask import request
from flask import Blueprint
from flask.ext.login import LoginManager, login_required, UserMixin, login_user, logout_user, current_user, make_secure_token
from requests_oauthlib import OAuth2Session
from scaffold import web
from libs.mail import sendmail
from pages import header, footer
from pages import profile
from data import site_user
from config.settings import *
from constants import *
web.load_widgets('widgets')
authorize_pages = Blueprint('authorize_pages', __name__, template_folder='templates')
login_manager = LoginManager()
login_manager.login_view = '/login'
def is_weak_password(password1, password2):
if password1 != password2:
password1 = password2 = None
return True
# TODO check length and chars
password1 = password2 = None
return False
def todict(data):
new_dict = {}
for key, value in data.items():
new_dict[key] = value
return new_dict
class User(UserMixin):
def __init__(self, user_id, active=True):
print 'logged in ###########'
print user_id
user_details = site_user.get_user_details({'id': user_id}).get()
self.active = False
print user_details
if user_details:
#~ self.check_password(user_details.get('password'))
self.id = user_id
self.name = user_details.get('username')
self.team_id = user_details.get('team_id', 1)
self.active = active
def get_id(self):
return self.id
def is_active(self):
return self.active
def is_authenticated(self):
return self.active
def get_auth_token(self):
return make_secure_token(self.name, key='deterministic')
@login_manager.user_loader
def load_user(userid):
return User(userid)
@login_manager.token_loader
def load_token(request):
token = request.headers.get('Authorization')
if token is None:
token = request.args.get('token')
if token is not None:
username, password = token.split(":") # naive token
print username
print password
user_entry = User.get(username)
if (user_entry is not None):
user = User(user_entry[0], user_entry[1])
if (user.password == password):
return user
return None
def auth_required():
if not session.get('user_id'):
redirect(domain + '/login', 301)
@authorize_pages.route("/register", methods=['GET'])
def register_form():
header('Register for access')
web.page.create('Register for access')
web.page.section(web.register_form.create().render())
web.template.body.append(web.page.render())
return make_response(footer())
@authorize_pages.route("/register", methods=['POST'])
def register_submit():
data = {}
data['email'] = request.form.get('email')
data['username'] = request.form.get('email')
data['first_name'] = request.form.get('name').strip().split()[0]
data['last_name'] = request.form.get('name').strip().split()[-1]
data['password'] = request.form.get('password')
data['password_confirm'] = request.form.get('password')
data['password'] = generate_password_hash(request.form.get('password'))
#TODO password strength tests
if is_weak_password(request.form.get('password'), request.form.get('password_confirm')):
print 'password not strong enough'
redirect('/register')
header('Your account has been registered')
web.page.create('Your account has been registered')
new_user = site_user.create()
new_user.execute(data)
flash('Your account has now been created')
web.template.body.append(web.page.render())
return make_response(footer())
@authorize_pages.route("/oauth", methods=['GET'])
@authorize_pages.route("/oauth/", methods=['GET'])
@authorize_pages.route("/oauth/<provider>", methods=['GET'])
def oauth(provider=None):
oauth_verify = True
oauth_provider = oauth_conf.get('google')
oauth_access_type = ''
oauth_approval_prompt = ''
if oauth_live is False:
oauth_verify = False
oauth_access_type = 'offline'
oauth_approval_prompt = "force"
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
print session
if provider:
oauth_session = OAuth2Session(
oauth_provider.get('client_id'),
scope=oauth_provider.get('scope'),
redirect_uri=oauth_provider.get('redirect_uri'))
# offline for refresh token
# force to always make user click authorize
#generate the google url we will use to authorize and redirect there
authorization_url, state = oauth_session.authorization_url(
oauth_provider.get('auth_uri'),
access_type=oauth_access_type,
approval_prompt=oauth_approval_prompt)
# State is used to prevent CSRF, keep this for later, make sure oauth returns to the same url.
session['oauth_state'] = state
return redirect(authorization_url)
print session
#allready authorised so lets handle the callback
oauth_session = OAuth2Session(
oauth_provider.get('client_id'),
state=session['oauth_state'],
redirect_uri=oauth_provider.get('redirect_uri'))
token = oauth_session.fetch_token(
oauth_provider.get('token_uri'),
client_secret=oauth_provider.get('client_secret'),
authorization_response=request.url,
verify=oauth_verify)
# Fetch a protected resource, i.e. user profile
r = oauth_session.get('https://www.googleapis.com/oauth2/v1/userinfo')
oauth_user = r.json()
#https://www.googleapis.com/auth/plus.login
#https://www.googleapis.com/auth/plus.me
print oauth_user
user_details = site_user.get_by_email({
'email': oauth_user.get('email')
}).get()
if not user_details:
flash('Your new profile has been created, and your now logged in')
site_user.create().execute({
'email': oauth_user.get('email'),
'password': 'oauth',
'profile_image': oauth_user.get('picture'),
'username': oauth_user.get('email'),
'first_name': oauth_user.get('given_name'),
'last_name': oauth_user.get('family_name')})
user_details = site_user.get_by_email({
'email': oauth_user.get('email')
}).get()
user = User(user_details.get('user_id'))
login_user(user)
site_user.update_last_login().execute(user_details)
return redirect('/profile')
@authorize_pages.route("/change-password/<code>", methods=['GET'])
@authorize_pages.route("/change-password", methods=['GET'])
def change_password(code=None):
#if we have a code this is a password reset, so try and login the user first
print code
site_user.delete_password_reset().execute({})
if code:
user_details = site_user.get_user_by_reset_code({'reset_code': code}).get()
print user_details
if not user_details:
#invalid code so pretend the page does not even exist
return abort(404)
#check the code has not expired
#datetime.datetime.now() + datetime.timedelta(minutes=15)
has_date_expired = user_details.get('created') + datetime.timedelta(minutes=60)
if has_date_expired < datetime.datetime.now():
print 'date expired'
#date expired so clean up and pretend the page does not exist
return abort(404)
#challenge passed so login the user so they can change there password
login_user(
User(user_details.get('user_id'))
)
session['user_id'] = str(user_details.get('user_id'))
web.template.create('Maidstone Hackspace - Profile')
header('User profile')
web.page.create('Change password')
web.page.section(
web.change_password_box.create().render()
)
web.template.body.append(web.page.render())
return make_response(footer())
@login_required
@authorize_pages.route("/change-password", methods=['POST'])
def change_password_submit(code=None):
if not session.get('user_id'):
abort(404)
user_details = site_user.authorize({
'id': session.get('user_id')}).get()
if is_weak_password(request.form.get('password'), request.form.get('password_confirm')):
print 'password not strong enough'
redirect('/login')
pw_hash = generate_password_hash(request.form.get('password'))
site_user.change_password().execute({'id': user_details.get('user_id'), 'password': pw_hash})
web.template.create('Maidstone Hackspace - Profile')
header('User Profile')
web.page.create('Password change complete')
web.page.section(
'Your password has successfull been changed'
)
web.template.body.append(web.page.render())
return make_response(footer())
@authorize_pages.route("/reset-password", methods=['GET'])
def reset_password():
web.template.create('Maidstone Hackspace - Login')
header('Members Login')
web.page.create('Forgot password reset')
web.page.section(
web.password_box.create('Please enter your E-Mail account', reset=True).render()
)
web.template.body.append(web.page.render())
return make_response(footer())
@authorize_pages.route("/reset-password", methods=['POST'])
def reset_password_submit():
user_details = site_user.get_by_username({
'email': request.form.get('email')}).get()
reset_code = hashlib.sha256(str(uuid.uuid4())).hexdigest()
if user_details:
site_user.create_password_reset() \
.on_duplicate() \
.execute({
'user_id': str(user_details.get('user_id')),
'reset_code': reset_code})
l=web.link.create(title='Change password', content='Click to change password',link="{domain}change-password/{resetcode}".format(**{'domain':app_domain, 'resetcode': reset_code})).render()
body = "Please follow the link below to change your password.\n" + l
body += "{domain}change-password/{resetcode}".format(**{'domain':app_domain, 'resetcode': reset_code})
sendmail().send(from_address='no-reply@maidstone-hackspace.org.uk', to_address='oly@leela', subject="Reset password request", body=body)
# display success page, dont give away anything about if the email is actually registered
web.template.create('Maidstone Hackspace - Password reset')
header('Password reset')
web.page.create('Password reset sent')
web.page.section(
web.paragraph.create('If this E-Mail is registered you will shortly be reciving an E-Mail with reset details').render()
)
web.template.body.append(web.page.render())
return make_response(footer())
@authorize_pages.route("/login", methods=['GET'])
def login_screen():
web.template.create('Maidstone Hackspace - Login')
header('Members Login')
web.page.create('Member Login')
web.page.section(
web.login_box.create().enable_oauth('google').render()
)
#~ web.template.body.append(web.messages.render())
web.template.body.append(web.page.render())
return make_response(footer())
@authorize_pages.route("/login", methods=['POST'])
def login_screen_submit():
"""handle the login form submit"""
# try to find user by username
user_details = site_user.get_by_username({
'email': request.form.get('username')}).get()
#not found so lets bail to the login screen
if not user_details:
flash('Failed to login with that username and password, please retry.')
return login_screen()
#now lets verify the users password, and bail if its wrong
pw_hash = generate_password_hash(request.form.get('password'))
if check_password_hash(pw_hash, user_details.get('password')):
flash('Failed to login with that username and password, please retry.')
return login_screen()
#login user and redirect to profile
login_user(
User(user_details.get('user_id'))
)
flash('You have successfully logged in !')
#~ session['username'] = user_details.get('username', 'anonymous')
#~ session['user_id'] = str(user_details.get('user_id'))
site_user.update_last_login(user_details)
return redirect('/profile')
@authorize_pages.route("/logout")
@login_required
def logout():
logout_user()
return redirect('/')

81
site/config/settings.py Normal file
View File

@ -0,0 +1,81 @@
import os
from scaffold.core.data.database import db
from scaffold import web
schema = 'https:'
domain = '127.0.0.1'
port = '5000'
rel_uri = '//127.0.0.1:5000'
app_domain = 'http:%s' % rel_uri
app_email_template_path = 'templates/email/'
from_email = 'no-reply@maidstone-hackspace.org.uk'
flask_secret_key = '4466ae96-849f-4fbe-a469-3295bf1a13f5'
database = {
'charset': 'utf8',
'use_unicode': True,
'type': 'mysql',
'host': '127.0.0.1',
'user': 'root',
'passwd': "",
'db': "maidstone_hackspace",
'port': 3306}
oauth_live = False
oauth_redirect_uri = app_domain + '/oauth'
oauth_conf = {
'google': {},
}
gocardless_enviroment = 'sandbox'
gocardless_credentials = {
'app_id': '',
'app_secret': '',
'access_token': '',
'merchant_id': ''
}
if os.path.exists('config/settings_dev.py'):
print 'Using settings for dev enviroment'
from settings_dev import *
if os.path.exists('config/settings_testing.py'):
print('Using settings for test enviroment')
from settings_testing import *
if os.path.exists('config/settings_live.py'):
print('Using settings for live enviroment')
from settings_live import *
with web.template as setup:
#css
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-navigation-white.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-action-white.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-content-white.css" media="" type="text/css" />')
#javascript
setup.persistent_header('<script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script>')
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>')
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>')
setup.persistent_header('<script type="text/javascript" src="/static/js/default.js"></script>')
#other favicon etc
setup.persistent_header('<link rel="icon" type="image/png" href="/static/images/favicon.png">')
setup.persistant_uris(
schema=schema,
domain=domain,
port=port)
db.config(database)

View File

@ -11,8 +11,8 @@ banner_images = [
('/static/images/banners/microscope.jpg', '', 'Microscope', ''),
('/static/images/banners/object_avoiding_robot.jpg', '', 'Object avoiding robot', ''),
('/static/images/banners/rocket_camera.jpg', 'Rocket Camera', 'Rocket Camera', '')]
#~ ('/static/template/images/example-01.jpg', '', 'title', 'intro text'),
#~ ('/static/template/images/example-02.jpg', '', 'title', 'intro text')]
#~ ('/static/images/example-01.jpg', '', 'title', 'intro text'),
#~ ('/static/images/example-02.jpg', '', 'title', 'intro text')]
tile_images = [
('/static/images/tiles/malta-inn.jpg',),
@ -38,3 +38,10 @@ email_server = {
'port': 465,
'from': 'support@maidstone-hackspace.org.uk',
'to': 'support@maidstone-hackspace.org.uk'}
url_home= '/'
url_profile = '/profile'
url_change_password = '/change_password'
url_change_password = '/reset_password'
url_login = '/login'

0
site/data/__init__.py Normal file
View File

45
site/data/equipment.py Normal file
View File

@ -0,0 +1,45 @@
import os
import time
import sys
sys.path.append(os.path.abspath('../../../../scaffold/'))
sys.path.insert(0,os.path.abspath('../../../../scaffold/'))
from scaffold.core.data.select import select_data
from scaffold.core.data.insert import insert_data
from scaffold.core.data.update import update_data
from scaffold.core.data.delete import delete_data
from scaffold.core.data.sql import query_builder
query_builder.query_path = os.path.abspath('./data/sql/')
class create(insert_data):
table = 'requests'
required = {'user_id', 'name'}
columns = {'user_id', 'name'}
columns_optional = {'price', 'description', 'url'}
class update(update_data):
#~ debug = True
table = 'requests'
required = {'id', 'user_id'}
columns = {'user_id', 'name'}
columns_where = {'id'}
columns_optional = {'price', 'description', 'url'}
class get_requests(select_data):
debug = True
#~ limit_rows = False
pagination_rows = 100
required = {}
#~ query_str = 'select id, user_id, name, description, url, price, count(user_id) as quantity from maidstone_hackspace.requests group by name'
query_str = 'select id, user_id, name, description, url, price as quantity from maidstone_hackspace.requests order by name'
columns = {}
class get_request(select_data):
table = 'requests'
required = {'id'}
columns = {'*'}
#query_str = 'select id, user_id, name, description, url, price, count(user_id) as quantity from maidstone_hackspace.requests group by name'
columns_where = {'id'}
#columns = {}

21
site/data/members.py Normal file
View File

@ -0,0 +1,21 @@
import os
import time
from scaffold.core.data.select import select_data
from scaffold.core.data.insert import insert_data
from scaffold.core.data.update import update_data
from scaffold.core.data.delete import delete_data
from scaffold.core.data.sql import query_builder
query_builder.query_path = os.path.abspath('./data/sql/')
class get_members(select_data):
required = {}
query_file = 'member_list.sql'
columns = {}
class get_member_profile(select_data):
required = {'id'}
query_file = 'get_users.sql'
columns_where = {'id'}

19
site/data/profile.py Normal file
View File

@ -0,0 +1,19 @@
import os
import time
from scaffold.core.data.select import select_data
from scaffold.core.data.insert import insert_data
from scaffold.core.data.update import update_data
from scaffold.core.data.delete import delete_data
from scaffold.core.data.sql import query_builder
query_builder.query_path = os.path.abspath('./data/sql/')
class update_description(update_data):
#~ debug = True
table = 'user_detail'
required = {'user_id', 'description', 'skills'}
columns = {'user_id', 'description', 'skills'}

81
site/data/site_user.py Normal file
View File

@ -0,0 +1,81 @@
import os
import time
from scaffold.core.data.select import select_data
from scaffold.core.data.insert import insert_data
from scaffold.core.data.update import update_data
from scaffold.core.data.delete import delete_data
from scaffold.core.data.sql import query_builder
query_builder.query_path = os.path.abspath('./data/sql/')
class create(insert_data):
table = 'users'
required = {'email', 'password', 'username', 'first_name', 'last_name', 'created'}
columns = {'email', 'password', 'username', 'first_name', 'last_name', 'created'}
columns_optional = {'profile_image'}
def calculated_data(self):
return {'created': time.strftime('%Y-%m-%d %H:%M:%S')}
def set(self, data):
data['created'] = time.strftime('%Y-%m-%d %H:%M:%S')
super(create, self).set(data)
class update_last_login(update_data):
#~ table = 'users'
debug = True
query_str = "update `users` set `last_login`=now() where id=%(user_id)s"
required = {'user_id'}
#~ columns = {'id'}
columns_where = {}
class delete_password_reset(delete_data):
"""clean up expired password resets"""
table = 'user_password_reset'
sql_where = 'where DATE_ADD(created, INTERVAL 1 HOUR) < now()'
required = {}
class create_password_reset(insert_data):
table = 'user_password_reset'
required = {'user_id', 'reset_code'}
class get_user_by_reset_code(select_data):
required = {'reset_code'}
query_file = 'get_user_password_reset.sql'
columns_where = ['reset_code']
class change_password(update_data):
table = 'users'
required = {'id', 'password'}
columns_where = ['password']
sql_where = 'id=%(id)s'
class get_users(select_data):
required = {}
query_file = 'get_users.sql'
class get_user_details(select_data):
#~ debug = True
required = {'id'}
query_file = 'get_user_detail.sql'
columns_where = {'users.id'}
class get_by_email(select_data):
required = {'email'}
query_file = 'get_users.sql'
columns_where = {'email'}
class get_by_username(select_data):
required = {'email'}
query_file = 'get_user_credentials.sql'
columns_where = {'email'}
class authorize(select_data):
required = {'id'}
query_file = 'get_user_credentials.sql'
columns_where = {'id'}

View File

@ -0,0 +1 @@
select id as user_id, username, email, password from users

View File

@ -0,0 +1,4 @@
select users.id as user_id, members.id as member_id, username, first_name, last_name, email, users.profile_image, last_login, description, skills
from users
left join members on users.id=members.user_id
left join user_detail on users.id = user_detail.user_id

View File

@ -0,0 +1 @@
select id as user_id, reset_code, created from user_password_reset

View File

@ -0,0 +1 @@
select id as user_id, username, first_name, email, profile_image, last_login from users

View File

@ -0,0 +1,3 @@
select users.id as user_id, first_name, last_name, users.profile_image, description, skills
from users
left join user_detail on user_detail.user_id=users.id

View File

@ -6,8 +6,7 @@ import argparse
sys.path.append(os.path.abspath('../../../scaffold/'))
sys.path.insert(0,os.path.abspath('../../../scaffold/'))
from scaffold.web import web as html
from scaffold.web import www
from scaffold import www
from libs.rss_fetcher import feed_reader

File diff suppressed because one or more lines are too long

View File

@ -2,22 +2,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:sa="/">
<head>
<link rel="stylesheet" id="navigationCss" href="/static/template/default.css" media="" type="text/css" />
<link rel="stylesheet" id="navigationCss" href="/static/template/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />
<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />
<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />
<script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>
<script type="text/javascript" src="/static/js/default.js"></script>
<link rel="icon" type="image/png" href="/static/images/favicon.png">
<title>Maidstone Hackspace - Screw sorting competition</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="headerstrip"><nav class="navstrip"><div class="left"><img src="/static/template/images/hackspace.png" class="mini-logo"><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="social"><div class="btn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="MHackspace">Tweet</a></div><div class="btn"><div class="fb-share-button" data-href="http://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="btn"><script type="IN/Share" data-url="http://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="btn"><div size="standard" class="g-plusone" data-href="http://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
<div id="headerstrip"><nav class="navstrip"><div class="left"><a id="mini_logo" href="/login"><img src="/static/images/hackspace.png" class="mini-logo"></a><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="social"><div class="btn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="MHackspace">Tweet</a></div><div class="btn"><div class="fb-share-button" data-href="http://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="btn"><script type="IN/Share" data-url="http://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="btn"><div size="standard" class="g-plusone" data-href="http://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
<nav id="leftNav" class="menu" >
<ul>
<li class="active mi0"><a href="/" >Home</a></li>
<li class="mi1"><a href="/chat" >Chat</a></li>
<li class="mi2"><a href="#mailing-list-signup" >Contact</a></li>
<li class="mi3"><a href="/login" >login</a></li>
</ul>
<div style="clear:both;"></div>
</nav>
@ -84,7 +86,8 @@ This kit comes with an arduino board and various sensors and components, list be
</div>
<div id="footer"><div id="footertop"></div><div id="footerbottom"><div class="container"><div class="copyright">&copy;2015 Maidstone Hackspace</div><div id="mailing-list-signup" class="google-groups-signup"><h3>Signup and make yourself known</h3><form class="block" name="signup" method="get" action="http://groups.google.com/group/maidstone-hackspace/boxsubscribe"><label for="groups-email">Email Address</label><input id="groups-email" name="email" class="required"/><button type="submit" />Subscribe</button><a href="http://groups.google.com/group/maidstone-hackspace">Browse Archives</a></form><div style="clear:both;"></div><div></div></div><div>
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<div id="ajaxPopup" class="hide" ></div><script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<script><!--//--><![CDATA[//><!--!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
//]]></script>
@ -109,6 +112,15 @@ ga('create', 'UA-63373181-1', 'maidstone-hackspace.org.uk');
ga('send', 'pageview');
$(document).ready(function(){
$('#mini_logo').on("click", function(e){
e.preventDefault();
$('#member_navigation').toggle();
});
});
var app = angular.module('myApp', ['ngAnimate']);
app.controller('sliderController', function($scope, $interval) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,17 +4,37 @@ import requests
from lxml import etree
from flask import Flask
from flask import make_response
from flask.ext.login import LoginManager, login_required
sys.path.append(os.path.abspath('../../../scaffold/'))
sys.path.insert(0,os.path.abspath('../../../scaffold/'))
from config import settings
import generate
from pages import homepage
from pages import chat
from pages import blog
from pages import competition
from pages import members
from pages.google_groups import google_groups_pages
from pages.equipment import equipment_pages
from pages.profile import profile_pages
from authorize import authorize_pages, login_manager
web_app = Flask(__name__, static_url_path='/static')
web_app.config['PROPAGATE_EXCEPTIONS'] = True
web_app.secret_key = settings.flask_secret_key
login_manager.init_app(web_app)
web_app.register_blueprint(authorize_pages)
web_app.register_blueprint(equipment_pages)
web_app.register_blueprint(profile_pages)
web_app.register_blueprint(google_groups_pages)
# local testing server, add your pages here
@web_app.route("/examples/", methods=['GET'])
def examples():
"""temporary for testing / examples"""
@ -30,10 +50,34 @@ def index():
"""home page"""
return make_response(homepage.index())
#~ @web_app.route("/competition/", methods=['GET'])
#~ def competition_index():
#~ """competition page"""
#~ return make_response(competition.index())
#~ @login_required
#~ @web_app.route("/equipment", methods=['GET'])
#~ def equipment_view():
#~ """home page"""
#~ return make_response(equipment.index())
#~ @login_required
#~ @web_app.route("/equipment/edit/<request_id>/", methods=['GET'])
#~ def equipment_edit_view(request_id):
#~ """home page"""
#~ return make_response(equipment.edit(request_id))
#~ @login_required
#~ @web_app.route("/equipment", methods=['POST'])
#~ def equipment_submit():
#~ """home page"""
#~ equipment.insert()
#~ return make_response(equipment.index())
@web_app.route("/members/", methods=['GET'])
def members_index():
"""list of members"""
return make_response(members.index())
@web_app.route("/members/<user_id>/<name>", methods=['GET'])
def members_profile(user_id, name):
"""members profile"""
return make_response(members.profile(user_id, name))
@web_app.route("/chat/", methods=['GET'])
def chat_index():

26
site/libs/mail.py Normal file
View File

@ -0,0 +1,26 @@
from mailer import Mailer
from mailer import Message
class sendmail:
host = 'localhost'
charset = 'utf-8'
subject_prefix = ''
@classmethod
def set_server(cls, host='localhost', charset='utf-8'):
cls.host = host
def __call__(self, **args):
return self
def send(self, from_address, to_address, subject, body='', html=True):
message = Message(From="me@example.com",
To=to_address,
charset=self.charset)
message.Subject = "%sAn HTML Email" % self.subject_prefix
message.Html = body
message.Body = body
sender = Mailer(self.host)
sender.send(message)

View File

@ -46,7 +46,7 @@ class feed_reader:
html_cleaner.remove_tags = ['script', 'iframe', 'link', 'style', 'img', 'div']
#~ html_cleaner.allow_tags = ['a', 'p', 'strong']
filter_by_date = datetime.datetime.now() - datetime.timedelta(days=int(1.5*365)) # 1 and a half years ago
filter_by_date_expire = datetime.datetime.now() - datetime.timedelta(days=int(1.5*365)) # 1 and a half years ago
html_img_cleaner = Cleaner(allow_tags=['img'], remove_unknown_tags=False)
html_img_cleaner.allow_tags = ['img']
@ -54,6 +54,8 @@ class feed_reader:
html_parser = lxml.etree.HTMLParser()
xml_parser = lxml.etree.XMLParser(remove_blank_text=True, ns_clean=True, encoding='utf-8')
enable_date_filter = True
def __init__(self, feed_details, timeout=5):
self.results = {}
for feed_info in feed_details:
@ -187,12 +189,20 @@ class feed_reader:
return True
return False
def filter_by_date(self, date):
"""filter the feed out by date"""
if self.enable_date_filter is False:
return True
if date > self.filter_by_date_expire:
return True
return False
def parse_feed(self):
"""Parse the items in the feed, filter out bad data and put in defaults"""
for item in self.feed.xpath('.//item', namespaces=namespaces):
date = self.convert_rfc822_to_datetime(self.fetch_node_text(item, 'pubDate'))
if date > self.filter_by_date and self.filter_by_tags(item):
if self.filter_by_date(date) and self.filter_by_tags(item):
author = self.format_author(self.fetch_node_text(item, 'author', self.author))
self.results.setdefault(author, []).append({
#~ self.results.append({

View File

@ -0,0 +1 @@
</>%<&>

View File

@ -0,0 +1 @@
<xml></xml>

16
site/migrate.py Normal file
View File

@ -0,0 +1,16 @@
import os
import sys
sys.path.insert(0, os.path.abspath('../../../scaffold/'))
from config import settings
from scaffold.core.data.database import db
print settings.database
db.config(settings.database)
from scaffold.core.data import migrations
from scaffold.core.data.migrations import export_schema, import_schema
#export_schema()
import_schema()

View File

@ -3,60 +3,68 @@ import sys
from libs.rss_fetcher import feed_reader
from scaffold.web import web as html
from scaffold.web import www
from scaffold.web import webpage as html
import constants as site
from flask.ext.login import current_user
web = html()
web.load_widgets('widgets')
web.template.create('Maidstone Hackspace', 'Hackspace for Maidstone, kent. for collaberation and discussion for artists, designers, makers, hackers, programmers, tinkerer, professionals and hobbyists.')
web.template.append('<link rel="icon" type="image/png" href="/static/template/images/icon.png">')
web.template.append('<link rel="icon" type="image/png" href="/static/images/icon.png">')
#paths
web.document_root = os.path.abspath('./')
web.template.domain = 'http://maidstone-hackspace.org.uk/'
web.template.theme_full_path = os.path.abspath('./static/template') + os.sep
web.template.theme_full_path = os.path.abspath('./static') + os.sep
domain = 'http://192.168.21.41:5000/'
image_path = domain + os.sep + 'template' + os.sep + 'images' + os.sep
image_path = domain + os.sep + 'images' + os.sep
with web.template as setup:
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/template/default.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/template/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />')
#setup.persistent_header('<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.9.4/angular-material.min.css">')
#setup.persistent_header('<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:300,400,500,700,400italic">')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-navigation-white.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-action-white.css" media="" type="text/css" />')
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-content-white.css" media="" type="text/css" />')
setup.persistent_header('<script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script>')
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>')
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>')
setup.persistent_header('<script type="text/javascript" src="/static/js/default.js"></script>')
#setup.persistent_header('<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script>')
#setup.persistent_header('<script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.2/angular-material.min.js"></script>')
setup.persistent_header('<link rel="icon" type="image/png" href="/static/images/favicon.png">')
#~ <meta property="og:title" content="The Rock" />
#~ <meta property="og:type" content="video.movie" />
#~ <meta property="og:url" content="http://www.imdb.com/title/tt0117500/" />
#~ <meta property="og:image" content="http://ia.media-imdb.com/images/rock.jpg" />
def header(title, description='Maidstone Hackspace is a shared space where artists, designers, makers, hackers, programmers, tinkerers, professionals and hobbyists can work on their projects', url=''):
# logo and social links at very top of the page
web.header_strip.create({})
#web.header_strip.social(web.google_plus.create(web.template.domain, plus=True, share=False, comments=False).render())
web.header_strip.create({'logged_in': current_user and current_user.is_authenticated})
web.header_strip.social(web.like.create(url=web.template.domain + url, plus=True, linkedin=True, facebook=True, twitter='MHackspace').render())
web.template.body.append(web.header_strip.render())
# navigation
web.menu.create('/' + url, 'leftNav')
web.menu.create('/' + url).set_id('leftNav')
web.menu * site.page_menu
if current_user and current_user.is_authenticated:
web.menu.append('logout', '/logout')
web.navigation_bar.create(hide=(False if url=='/profile' else True))
web.navigation_bar.append('Profile', '/profile')
web.navigation_bar.append('Equipment', '/equipment')
web.navigation_bar.append('Members', '/members')
web.navigation_bar.append('Mailing List', '/mailing-list')
web.template.body.append(web.navigation_bar.render())
else:
web.menu.append('login', '/login')
web.template.body.append(web.menu.render())
# extra javascript libraries
#web.template.javascript_includes.append('<script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script>')
#web.template.javascript_includes.append('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>')
#web.template.javascript_includes.append('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>')
#~ web.template.header.append('<link rel="icon" type="image/png" href="/static/images/favicon.png">')
def footer():
web.footer_content.create().append(
web.google_groups_signup.create(' and make yourself known','maidstone-hackspace').set_id('mailing-list-signup').render())

20
site/pages/calendar.py Normal file
View File

@ -0,0 +1,20 @@
import constants as site
from libs.rss_fetcher import feed_reader
from pages import web
from pages import header, footer
def index():
header('Maidstone Hackspace Calendar')
web.template.body.append(web.header_strip.create({}).render())
web.template.body.append(web.menu.render())
web.calendar.create('https://www.google.com/calendar/feeds/0rtjmmdbsb8e9351mkip02g8n8%40group.calendar.google.com/public/basic')
web.page.create(web.title.create('IRC Chat Room').render())
web.page.create(web.paragraph.create('Pop in and say hi, please be patient users tend to idle and will respond when they get a chance.').render())
web.page.section(web.chat.create('maidstone-hackspace').render())
web.template.body.append(web.page.render())
return footer()

111
site/pages/equipment.py Normal file
View File

@ -0,0 +1,111 @@
import sys
from flask import session
from flask import request
from flask import Blueprint
from flask import make_response
from flask.ext.login import current_user, login_required
import constants as site
from libs.rss_fetcher import feed_reader
from pages import web
from pages import header, footer
from data import equipment
equipment_pages = Blueprint('equipment_pages', __name__, template_folder='templates')
@equipment_pages.route("/equipment/add/", methods=['GET'])
@equipment_pages.route("/equipment/edit/<request_id>/", methods=['GET'])
@login_required
def equipment_view(request_id=None):
"""home page"""
equipment_data = request.form
if request_id:
equipment_data = equipment.get_request({'id': request_id}).get()
web.form.create('Equipment wish list', '/equipment')
web.form.append(name='id', label='', placeholder='', value=equipment_data.get('id') or '', input_type='hidden')
web.form.append(name='name', label='name', placeholder='Screws 3.5 x 20mm', value=equipment_data.get('name') or '')
web.form.append(name='url', label='url', placeholder='Link to example', value=equipment_data.get('url') or '')
web.form.append(name='description', label='description', placeholder='Notes / Description', value=equipment_data.get('description') or '')
web.form.append(name='price', label='price', placeholder='10.00', value=equipment_data.get('price') or '')
return make_response(web.form.render())
@equipment_pages.route("/equipment", methods=['POST'])
@login_required
def equipment_submit():
insert()
return make_response(index())
@equipment_pages.route("/equipment/delete/<request_id>", methods=['GET'])
@login_required
def equipment_delete(request_id):
#~ delete()
return make_response(index())
def insert():
data = {}
data['id'] = request.form.get('id')
data['name'] = request.form.get('name')
data['user_id'] = current_user.get_id()
data['price'] = request.form.get('price')
data['url'] = request.form.get('url')
data['description'] = request.form.get('description')
if data['id']:
equipment.update().execute(data)
else:
equipment.create().execute(data)
@equipment_pages.route("/equipment", methods=['GET'])
@login_required
def index(request_id=None):
web.template.create('Maidstone Hackspace - Equipment')
header('User Profile')
web.page.create('Equipment wish list')
web.list.create()
for item in equipment.get_requests():
if item.get('name'):
values = []
if item.get('url'):
values.append(
web.link.create(item.get('name'), item.get('name'), item.get('url')).render()
)
else:
values.append(item.get('name'))
if item.get('price'):
values.append( '&pound;' + str(item.get('price')))
if item.get('user_id') == current_user.get_id():
values.append(
web.link.create('edit', 'edit', '/equipment/edit/%s' % item.get('id')).set_classes('ajaxPopup').render())
if item.get('description'):
web.list.append(' - '.join(values) + web.paragraph.create(item.get('description')).render())
else:
web.list.append(' - '.join(values))
web.paragraph.create('''This is wanted list, if you can donate any of these items great,
if not we will look at running pledges or using hackspace funds to get these items where appropriate.''')
web.page.section(web.paragraph.render())
web.page.section(web.list.render())
web.template.body.append(web.page.render())
web.template.body.append(
web.action_bar.create(
url='/equipment/add',
title='Add equipment',
node_id='add-equipment',
classes='ajaxPopup icon-content-white icon-content-white-ic_add_white_24dp'
).render()
)
web.template.body.append(web.popup.create('').render())
return make_response(footer())

17
site/pages/examples.py Normal file
View File

@ -0,0 +1,17 @@
import constants as site
from libs.rss_fetcher import feed_reader
from pages import web
from pages import header, footer
def twitter():
web.template.create('Maidstone Hackspace')
header('Maidstone Hackspace Homepage')
web.page.create('')
web.twitter_feed.create(username='MHackspace', widget_id='606798560374484992')
web.page.section(
web.twitter_feed.render())
web.template.body.append(web.page.render())
return footer()

View File

@ -0,0 +1,31 @@
from flask import session
from flask import request
from flask import Blueprint
from flask import make_response
from flask.ext.login import current_user, login_required
import constants as site
from libs.rss_fetcher import feed_reader
from pages import web
from pages import header, footer
from data import equipment
google_groups_pages = Blueprint('google_group', __name__, template_folder='templates')
@login_required
@google_groups_pages.route("/mailing-list/", methods=['GET'])
def index(request_id=None):
web.template.create('Maidstone Hackspace - Mailing List')
header('Mailing List')
web.page.create('Mailing List')
web.google_groups.create(title='Title', name='maidstone-hackspace')
web.container.create(web.google_groups.render()).set_classes('margin_default')
web.page.section(web.container.render())
web.template.body.append(web.page.render())
return footer()

View File

@ -1,8 +1,8 @@
import constants as site
from libs.rss_fetcher import feed_reader
from pages import web
from scaffold import web
#~ from pages import web
from pages import header, footer
@ -13,9 +13,9 @@ def index():
web.page.section(
web.div.create(
web.images.create(
site.tile_images[0][0]
web.template.uri.add_domain(site.tile_images[0][0])
).append(
site.tile_images[1][0]
web.template.uri.add_domain(site.tile_images[1][0])
).render()
).set_classes('tile-right tile-image').render())
web.banner_slider.reset()
@ -49,11 +49,8 @@ def index():
web.div.create('').set_classes('panel')
web.twitter_feed.create(username='MHackspace', widget_id='606798560374484992')
feed = feed_reader(site.rss_feeds)
web.columns.create()
web.columns.append(web.twitter_feed.render())
feed = feed_reader(site.rss_feeds)
for row in feed:
web.tiles.create()
web.columns.append(

54
site/pages/members.py Normal file
View File

@ -0,0 +1,54 @@
from flask import session
from flask import request
from flask.ext.login import current_user, login_required
import constants as site
from libs.rss_fetcher import feed_reader
from pages import web
from pages import header, footer
from data import members
@login_required
def index():
web.template.create('Maidstone Hackspace - Members')
header('Members')
web.page.create('Members')
web.member_tiles.create()
for item in members.get_members():
print item
name = '%s %s' % (item.get('first_name'), item.get('last_name'))
user_id = '%s %s' % (item.get('first_name'), item.get('last_name'))
web.member_tiles.append(
name = name,
image = item.get('profile_image'),
description=item.get('description') or 'Reclusive raccoon',
link=item.get('user_id'),
skills=item.get('skills') or 'badger taunting')
web.container.create(web.member_tiles.render()).set_classes('members')
web.page.section(web.container.render())
web.template.body.append(web.page.render())
return footer()
@login_required
def profile(user_id, user_name):
web.template.create('Maidstone Hackspace - User profile')
header('User Profile')
user = members.get_member_profile({'id': user_id}).get()
web.page.create('')
name = '%s %s' % (user.get('first_name', ''), user.get('last_name', ''))
web.paragraph.create(
web.images.create(user.get('profile_image', '/static/images/hackspace.png'), name).add_attributes('width', '200').render()
)
web.paragraph.add(name)
web.paragraph.add('%s' % (user.get('email')))
web.paragraph.add('Last Login %s' % (user.get('last_login', '')))
web.paragraph.add('Member since %s' % (user.get('created', '')))
web.page.section(web.paragraph.render())
web.template.body.append(web.page.render())
return footer()

98
site/pages/profile.py Normal file
View File

@ -0,0 +1,98 @@
from flask import session
from flask import Blueprint
from flask import request
from flask import redirect, abort
from flask.ext.login import current_user, login_required
import constants as site
import gocardless
from libs.rss_fetcher import feed_reader
from pages import web
from pages import header, footer
from data.site_user import get_user_details
from data.profile import update_description
profile_pages = Blueprint('profile_pages', __name__, template_folder='templates')
@profile_pages.route("/profile", methods=['GET'])
@login_required
def index():
web.template.create('Maidstone Hackspace - User profile')
header('User Profile', url='/profile')
print current_user
user = get_user_details({'id': current_user.get_id()}).get()
name = '%s %s' % (user.get('first_name', '').capitalize(), user.get('last_name', '').capitalize())
web.page.create('%s - Profile' % name)
web.columns.create()
web.paragraph.create(
web.images.create(user.get('profile_image', '/static/images/hackspace.png'), name).add_attributes('width', '200').render()
)
web.paragraph.add(name)
web.paragraph.add('%s' % (user.get('email')))
web.paragraph.add('Last Login %s' % (user.get('last_login', '')))
web.paragraph.add('Member since %s' % (user.get('created', '')))
web.paragraph.add('Description %s' % (user.get('description', '')))
web.columns.append(web.paragraph.render())
web.paragraph.create(
web.link.create(
'Edit Description',
'Edit Description',
'/profile/details'
).set_classes('ajaxPopup').render())
web.form.create('Join Maidstone Hackspace', '/profile/membership')
web.form.append(name='amount', label='Subscription Amount', placeholder='20.00', value='20.00')
#~ web.form.append(name='skills', label='skills', placeholder='python, arduino, knitting')
web.form.render()
web.columns.append(web.paragraph.render())
web.columns.append(web.google_calendar.create().render())
web.columns.append(web.member_card.create(str(user.get('user_id')).zfill(5), name).render())
web.columns.append(web.form.render())
web.page.section(web.columns.render())
web.template.body.append(web.page.render())
web.template.body.append(web.popup.create('').render())
return footer()
@profile_pages.route("/profile/membership", methods=['POST'])
@login_required
def pay_membership():
import gocardless
gocardless.environment = gocardless_enviroment
gocardless.set_details(**gocardless_credentials)
url = gocardless.client.new_subscription_url(
amount=20.00,
interval_length=1,
interval_unit="month",
name="Membership Renewal for MH0001")
return redirect(url)
@profile_pages.route("/profile/details", methods=['GET'])
@login_required
def edit_profile():
user = get_user_details({'id': current_user.get_id()}).get()
web.form.create('Update your details', '/profile/update')
web.form.append(name='description', label='Description', placeholder='This is me i am great')
web.form.append(name='skills', label='skills', placeholder='python, arduino, knitting')
return web.form.render()
@profile_pages.route("/profile/update", methods=['POST'])
@login_required
def update_profile():
data = {
'user_id': current_user.get_id(),
'skills': request.form.get('skills'),
'description': request.form.get('description')}
update_description().execute(data)
return redirect('/profile')

View File

@ -0,0 +1,22 @@
table_name, column_name, column_type, default
#requests
#users
ALTER TABLE users ADD INDEX id_UNIQUE (id ASC);
ALTER TABLE users ADD INDEX member_reference_UNIQUE (member_reference ASC);
ALTER TABLE users ADD INDEX email_UNIQUE (email ASC);
#user_detail
ALTER TABLE user_detail ADD INDEX id_UNIQUE (id ASC);
ALTER TABLE user_detail ADD INDEX user_id_UNIQUE (user_id ASC);
ALTER TABLE user_detail ADD INDEX member_id_UNIQUE (member_id ASC);
#user_password_reset
ALTER TABLE user_password_reset ADD INDEX id_UNIQUE (id ASC);
ALTER TABLE user_password_reset ADD INDEX user_id_UNIQUE (user_id ASC);
ALTER TABLE user_password_reset ADD INDEX password_UNIQUE (reset_code ASC);

View File

@ -0,0 +1,69 @@
table_name, column_name, column_type, default
#requests
ALTER TABLE requests ADD COLUMN description varchar(255) NULL ;
ALTER TABLE requests CHANGE COLUMN description description varchar(255) NULL ;
ALTER TABLE requests ADD COLUMN id int(10) unsigned PRIMARY KEY (`id`) AUTO_INCREMENT ;
ALTER TABLE requests CHANGE COLUMN id id int(10) unsigned PRIMARY KEY (`id`) AUTO_INCREMENT ;
ALTER TABLE requests ADD COLUMN name varchar(45) NULL ;
ALTER TABLE requests CHANGE COLUMN name name varchar(45) NULL ;
ALTER TABLE requests ADD COLUMN price decimal(10,2) NULL ;
ALTER TABLE requests CHANGE COLUMN price price decimal(10,2) NULL ;
ALTER TABLE requests ADD COLUMN url varchar(255) NULL ;
ALTER TABLE requests CHANGE COLUMN url url varchar(255) NULL ;
ALTER TABLE requests ADD COLUMN user_id int(10) unsigned ;
ALTER TABLE requests CHANGE COLUMN user_id user_id int(10) unsigned ;
#users
ALTER TABLE users ADD COLUMN created timestamp NULL ;
ALTER TABLE users CHANGE COLUMN created created timestamp NULL ;
ALTER TABLE users ADD COLUMN email varchar(255) NULL ;
ALTER TABLE users CHANGE COLUMN email email varchar(255) NULL ;
ALTER TABLE users ADD COLUMN first_name varchar(45) NULL ;
ALTER TABLE users CHANGE COLUMN first_name first_name varchar(45) NULL ;
ALTER TABLE users ADD COLUMN id int(10) unsigned PRIMARY KEY (`id`) ;
ALTER TABLE users CHANGE COLUMN id id int(10) unsigned PRIMARY KEY (`id`) ;
ALTER TABLE users ADD COLUMN last_login varchar(45) NULL ;
ALTER TABLE users CHANGE COLUMN last_login last_login varchar(45) NULL ;
ALTER TABLE users ADD COLUMN last_name varchar(45) NULL ;
ALTER TABLE users CHANGE COLUMN last_name last_name varchar(45) NULL ;
ALTER TABLE users ADD COLUMN member_reference int(5) unsigned zerofill AUTO_INCREMENT ;
ALTER TABLE users CHANGE COLUMN member_reference member_reference int(5) unsigned zerofill AUTO_INCREMENT ;
ALTER TABLE users ADD COLUMN password varchar(160) NULL ;
ALTER TABLE users CHANGE COLUMN password password varchar(160) NULL ;
ALTER TABLE users ADD COLUMN profile_image varchar(255) NULL ;
ALTER TABLE users CHANGE COLUMN profile_image profile_image varchar(255) NULL ;
ALTER TABLE users ADD COLUMN status tinyint(2) NULL DEFAULT 0;
ALTER TABLE users CHANGE COLUMN status status tinyint(2) NULL DEFAULT 0;
ALTER TABLE users ADD COLUMN username varchar(25) ;
ALTER TABLE users CHANGE COLUMN username username varchar(25) ;
#user_detail
ALTER TABLE user_detail ADD COLUMN description text NULL ;
ALTER TABLE user_detail CHANGE COLUMN description description text NULL ;
ALTER TABLE user_detail ADD COLUMN id int(11) PRIMARY KEY (`id`) ;
ALTER TABLE user_detail CHANGE COLUMN id id int(11) PRIMARY KEY (`id`) ;
ALTER TABLE user_detail ADD COLUMN image varchar(45) NULL ;
ALTER TABLE user_detail CHANGE COLUMN image image varchar(45) NULL ;
ALTER TABLE user_detail ADD COLUMN member_id int(5) unsigned zerofill ;
ALTER TABLE user_detail CHANGE COLUMN member_id member_id int(5) unsigned zerofill ;
ALTER TABLE user_detail ADD COLUMN profile_image varchar(255) NULL ;
ALTER TABLE user_detail CHANGE COLUMN profile_image profile_image varchar(255) NULL ;
ALTER TABLE user_detail ADD COLUMN skills varchar(255) NULL ;
ALTER TABLE user_detail CHANGE COLUMN skills skills varchar(255) NULL ;
ALTER TABLE user_detail ADD COLUMN user_id int(11) unsigned ;
ALTER TABLE user_detail CHANGE COLUMN user_id user_id int(11) unsigned ;
#user_password_reset
ALTER TABLE user_password_reset ADD COLUMN created timestamp NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE user_password_reset CHANGE COLUMN created created timestamp NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE user_password_reset ADD COLUMN id int(11) PRIMARY KEY (`id`) AUTO_INCREMENT ;
ALTER TABLE user_password_reset CHANGE COLUMN id id int(11) PRIMARY KEY (`id`) AUTO_INCREMENT ;
ALTER TABLE user_password_reset ADD COLUMN reset_code varchar(160) ;
ALTER TABLE user_password_reset CHANGE COLUMN reset_code reset_code varchar(160) ;
ALTER TABLE user_password_reset ADD COLUMN user_id int(11) ;
ALTER TABLE user_password_reset CHANGE COLUMN user_id user_id int(11) ;

View File

@ -0,0 +1,4 @@
CREATE TABLE IF NOT EXISTS requests;
CREATE TABLE IF NOT EXISTS users;
CREATE TABLE IF NOT EXISTS user_detail;
CREATE TABLE IF NOT EXISTS user_password_reset;

View File

@ -1,11 +1,28 @@
html {background-color:#fff;height:100%;font-family:'Arial';font-size:18px;}
body {margin:0px;padding:0px;}
form button {margin:none;}
a {color:#fff;}
li p {margin: 20px 0px 0px 30px;}
.hide {display:none;}
#ajaxPopup {position:absolute;width:750px;height:550px;background-color:#fff;top:68px;left:50%;margin-left: -375px;}
#ajaxPopup legend {width:720px;padding:15px;color:#fff;background-color:#000;margin:0px;}
#ajaxPopup fieldset {border:0px;margin:0px;padding:0px;}
#ajaxPopup label {width:160px;color:#000;}
#ajaxPopup p {position:relative;}
#ajaxPopup input {position:absolute;left:160px;}
.margin_default {margin:10px;}
.header span{font-size:100px;}
.headerbar {background-color:#E7EAEF;}
.footer {width:100%:margin:auto;height:40px;background-color:#dddddd;border-top:1px solid #aaaaaa;border-bottom:1px solid #aaaaaa;}
.footerbar {background-color:#E7EAEF;border-top:1px solid #D2D2D2;border-bottom:1px solid #D2D2D2;margin-top:60px;}
.pageFooter{clear:both;}
.pageHeader{padding:20px;color:#fff;font-size:24px;}
.pagination{height:40px;font-size:16px;}
.pagination li.active{background-color:#0a2024;}
@ -44,8 +61,8 @@ h2 {margin-left:25px;color:#fff;}
h3 {color:#fff;}
li {padding-bottom:10px;line-height:150%;}
label {margin-bottom:10px;float:left;clear:both;display:block;color:#fff;}
input {width:100%;margin:0px;margin-bottom:20px;padding:10px;}
label {margin-bottom:10px;color:#fff;}
input {margin:0px;margin-bottom:20px;padding:10px;}
button {margin-bottom:20px;background-color: #fff; height: 48px; width:100%; border-radius: 3px;box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.2);}
.tile-right {margin-top:20px;width:230px;float:right;margin-right:20px;}
@ -72,7 +89,7 @@ height:48px;width:48px; -webkit-animation:spin 2s linear infinite ;-moz-animatio
#navstrip{}
.menu {position:absolute;left:0px;right:0px;height:40px;height:388px;top:68px;background-color:#00232D;z-index:-1;}
.menu {position:absolute;left:0px;right:0px;height:408px;top:68px;background-color:#00232D;z-index:-1;}
.menu ul {width:960px;margin:auto;height:40px;padding-left:20px;background-color:#0087A8;}
.menu li {width:130px;float:left;list-style-type:none;margin-top:10px;padding:00px;text-align:center;}
.menu li:hover {width:130px;float:left;list-style-type:none;border-bottom:4px solid #1C4085;}
@ -80,6 +97,8 @@ height:48px;width:48px; -webkit-animation:spin 2s linear infinite ;-moz-animatio
.menu li:hover {}
.page {width:980px;margin:auto;margin-top:155px;padding-bottom:48px;background-color:#0087A8;}
.page .messages{color:#fff;border:10px solid #0087A8;background-color:#00232D; font-weight:bold;}
.page .messages li{padding:10px;}
.columns{float:right;clear:right;width:460px;margin-left:20px;margin-bottom:20px;}
@ -135,7 +154,7 @@ height:48px;width:48px; -webkit-animation:spin 2s linear infinite ;-moz-animatio
.bullet-list li {margin:0px;margin-left:10px;line-height:100%;}
.tile {position:relative;background-color:#eee;width:460px;margin-left:20px;margin-bottom:20px;box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.26);}
.tile-img {margin:20px;width:420px;height:200px;overflow:hidden;background-repeat: no-repeat;background-position: center;background-image:url('/static/template/images/background.png');}
.tile-img {margin:20px;width:420px;height:200px;overflow:hidden;background-repeat: no-repeat;background-position: center;background-image:url('/static/images/background.png');}
.tile header {background-color: #00232D;width:100%;bottom:20px;top:220px;overflow:auto;left:20px;right:20px;text-align:justify;line-height:150%;font-size:12px;}
.tile h2 {line-height:150%;font-size:12px;margin-right:20px;}
.tile header a {color:#fff;}
@ -154,3 +173,50 @@ height:48px;width:48px; -webkit-animation:spin 2s linear infinite ;-moz-animatio
.social {z-index:1;position:absolute;right:0px;top:0px;margin-top:25px;}
.social .btn{float:left;margin-left:20px;}
.col {width:480px;float:left;}
#login_box {width:500px; margin:auto}
#login_box p {color:#fff;padding:0px;margin:0px;}
#login_box label {display:block;margin: 20px 0px 20px;}
#login_box input {margin: 20px 0px 0px;}
#login_box .providers {margin: 20px 0px 20px;}
.members .tile{ width:220px;float:left;}
.members .tile-img{margin:10px;width:200px;}
#member_navigation {position:absolute;top:68px;left:0px;width:200px;height:100%;background-color:#0087A8;}
#member_navigation a {color:#fff;font-weight:bold;}
#member_navigation ul {padding:0px;}
#member_navigation li {margin:0px;padding:10px;background-color:#0087A8;list-style-type: none;}
#member_navigation li:hover {background-color:#E7EAEF;}
.action-bar {overflow:hidden;position:fixed;right:50px;bottom:50px;width:65px;height:70px;}
.action-bar:hover {height:260px;}
.action-bar .container{position:absolute;left:0px;bottom:0px;width:62px;min-width:62px;max-width:62px;padding-bottom:5px;}
.action-bar-small {overflow:hidden;position:absolute;right:0px;top:40px;width:32px;height:32px;}
.action-bar .action-bar-button{margin-top:20px;}
.action-bar-button {display:block;padding:19px;background-color: #FF2670;border-radius: 100%;box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.26);z-index:5;}
.action-bar-button-small {display:block;padding:19px;background-color: #FF2670;border-radius: 100%;box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.26);z-index:5;}
.closePopup {position:absolute;top:12px;right:12px;background-color: #FF2670;border-radius: 100%;box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.26);z-index:5;}
#membercard{
background-color: #FF2670;border-radius: 14px;box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.26);
width: 430px;
height: 240px;
margin-left:20px;
/*
line-height: 240px;
*/
text-align: center;
position:relative;
}
#membercard .date {position:absolute;margin:25px;top:0px;left:0px;}
#membercard .container {position:relative;top:50%; width:100%;}
#membercard .middle {position:absolute;top:-60px;width:100%;}
.calendar {border:2px solid #000;}

View File

@ -0,0 +1,982 @@
.icon-action-white {
background-image: url('/static/images/css/sprite-action-white.png');
}
.icon-action-white-ic_perm_identity_white_24dp {
background-position: -5px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_3d_rotation_white_24dp {
background-position: -39px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_account_balance_wallet_white_24dp {
background-position: -5px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_account_balance_white_24dp {
background-position: -39px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_account_box_white_24dp {
background-position: -73px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_account_child_white_24dp {
background-position: -73px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_account_circle_white_24dp {
background-position: -5px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_add_shopping_cart_white_24dp {
background-position: -39px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_alarm_add_white_24dp {
background-position: -73px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_alarm_off_white_24dp {
background-position: -107px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_alarm_on_white_24dp {
background-position: -107px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_alarm_white_24dp {
background-position: -107px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_android_white_24dp {
background-position: -5px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_announcement_white_24dp {
background-position: -39px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_aspect_ratio_white_24dp {
background-position: -73px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_assessment_white_24dp {
background-position: -107px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_assignment_ind_white_24dp {
background-position: -141px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_assignment_late_white_24dp {
background-position: -141px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_assignment_return_white_24dp {
background-position: -141px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_assignment_returned_white_24dp {
background-position: -141px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_assignment_turned_in_white_24dp {
background-position: -5px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_assignment_white_24dp {
background-position: -39px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_autorenew_white_24dp {
background-position: -73px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_backup_white_24dp {
background-position: -107px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_book_white_24dp {
background-position: -141px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_bookmark_outline_white_24dp {
background-position: -175px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_bookmark_white_24dp {
background-position: -175px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_bug_report_white_24dp {
background-position: -175px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_cached_white_24dp {
background-position: -175px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_check_circle_white_24dp {
background-position: -175px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_class_white_24dp {
background-position: -5px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_credit_card_white_24dp {
background-position: -39px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_dashboard_white_24dp {
background-position: -73px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_delete_white_24dp {
background-position: -107px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_description_white_24dp {
background-position: -141px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_dns_white_24dp {
background-position: -175px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_done_all_white_24dp {
background-position: -209px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_done_white_24dp {
background-position: -209px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_event_white_24dp {
background-position: -209px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_exit_to_app_white_24dp {
background-position: -209px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_explore_white_24dp {
background-position: -209px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_extension_white_24dp {
background-position: -209px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_face_white_24dp {
background-position: -5px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_favorite_outline_white_24dp {
background-position: -39px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_favorite_white_24dp {
background-position: -73px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_find_in_page_white_24dp {
background-position: -107px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_find_replace_white_24dp {
background-position: -141px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_flip_to_back_white_24dp {
background-position: -175px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_flip_to_front_white_24dp {
background-position: -209px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_get_app_white_24dp {
background-position: -243px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_grade_white_24dp {
background-position: -243px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_group_work_white_24dp {
background-position: -243px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_help_white_24dp {
background-position: -243px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_highlight_remove_white_24dp {
background-position: -243px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_history_white_24dp {
background-position: -243px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_home_white_24dp {
background-position: -243px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_https_white_24dp {
background-position: -5px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_info_outline_white_24dp {
background-position: -39px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_info_white_24dp {
background-position: -73px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_input_white_24dp {
background-position: -107px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_invert_colors_white_24dp {
background-position: -141px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_label_outline_white_24dp {
background-position: -175px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_label_white_24dp {
background-position: -209px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_language_white_24dp {
background-position: -243px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_launch_white_24dp {
background-position: -277px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_list_white_24dp {
background-position: -277px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_lock_open_white_24dp {
background-position: -277px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_lock_outline_white_24dp {
background-position: -277px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_lock_white_24dp {
background-position: -277px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_loyalty_white_24dp {
background-position: -277px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_markunread_mailbox_white_24dp {
background-position: -277px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_note_add_white_24dp {
background-position: -277px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_open_in_browser_white_24dp {
background-position: -5px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_open_in_new_white_24dp {
background-position: -39px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_open_with_white_24dp {
background-position: -73px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_pageview_white_24dp {
background-position: -107px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_payment_white_24dp {
background-position: -141px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_perm_camera_mic_white_24dp {
background-position: -175px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_perm_contact_cal_white_24dp {
background-position: -209px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_perm_data_setting_white_24dp {
background-position: -243px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_perm_device_info_white_24dp {
background-position: -277px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_accessibility_white_24dp {
background-position: -311px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_perm_media_white_24dp {
background-position: -311px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_perm_phone_msg_white_24dp {
background-position: -311px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_perm_scan_wifi_white_24dp {
background-position: -311px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_picture_in_picture_white_24dp {
background-position: -311px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_polymer_white_24dp {
background-position: -311px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_print_white_24dp {
background-position: -311px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_query_builder_white_24dp {
background-position: -311px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_question_answer_white_24dp {
background-position: -311px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_receipt_white_24dp {
background-position: -5px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_redeem_white_24dp {
background-position: -39px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_reorder_white_24dp {
background-position: -73px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_report_problem_white_24dp {
background-position: -107px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_restore_white_24dp {
background-position: -141px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_room_white_24dp {
background-position: -175px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_schedule_white_24dp {
background-position: -209px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_search_white_24dp {
background-position: -243px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_applications_white_24dp {
background-position: -277px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_backup_restore_white_24dp {
background-position: -311px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_bluetooth_white_24dp {
background-position: -345px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_cell_white_24dp {
background-position: -345px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_display_white_24dp {
background-position: -345px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_ethernet_white_24dp {
background-position: -345px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_input_antenna_white_24dp {
background-position: -345px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_input_component_white_24dp {
background-position: -345px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_input_composite_white_24dp {
background-position: -345px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_input_hdmi_white_24dp {
background-position: -345px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_input_svideo_white_24dp {
background-position: -345px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_overscan_white_24dp {
background-position: -345px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_phone_white_24dp {
background-position: -5px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_power_white_24dp {
background-position: -39px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_remote_white_24dp {
background-position: -73px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_voice_white_24dp {
background-position: -107px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_settings_white_24dp {
background-position: -141px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_shop_two_white_24dp {
background-position: -175px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_shop_white_24dp {
background-position: -209px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_shopping_basket_white_24dp {
background-position: -243px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_shopping_cart_white_24dp {
background-position: -277px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_speaker_notes_white_24dp {
background-position: -311px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_spellcheck_white_24dp {
background-position: -345px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_star_rate_white_24dp {
background-position: -379px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_stars_white_24dp {
background-position: -379px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_store_white_24dp {
background-position: -379px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_subject_white_24dp {
background-position: -379px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_supervisor_account_white_24dp {
background-position: -379px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_swap_horiz_white_24dp {
background-position: -379px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_swap_vert_circle_white_24dp {
background-position: -379px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_swap_vert_white_24dp {
background-position: -379px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_system_update_tv_white_24dp {
background-position: -379px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_tab_unselected_white_24dp {
background-position: -379px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_tab_white_24dp {
background-position: -379px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_theaters_white_24dp {
background-position: -5px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_thumb_down_white_24dp {
background-position: -39px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_thumb_up_white_24dp {
background-position: -73px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_thumbs_up_down_white_24dp {
background-position: -107px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_toc_white_24dp {
background-position: -141px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_today_white_24dp {
background-position: -175px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_track_changes_white_24dp {
background-position: -209px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_translate_white_24dp {
background-position: -243px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_trending_down_white_24dp {
background-position: -277px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_trending_neutral_white_24dp {
background-position: -311px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_trending_up_white_24dp {
background-position: -345px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_turned_in_not_white_24dp {
background-position: -379px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_turned_in_white_24dp {
background-position: -413px -5px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_verified_user_white_24dp {
background-position: -413px -39px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_agenda_white_24dp {
background-position: -413px -73px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_array_white_24dp {
background-position: -413px -107px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_carousel_white_24dp {
background-position: -413px -141px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_column_white_24dp {
background-position: -413px -175px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_day_white_24dp {
background-position: -413px -209px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_headline_white_24dp {
background-position: -413px -243px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_list_white_24dp {
background-position: -413px -277px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_module_white_24dp {
background-position: -413px -311px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_quilt_white_24dp {
background-position: -413px -345px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_stream_white_24dp {
background-position: -413px -379px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_view_week_white_24dp {
background-position: -5px -413px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_visibility_off_white_24dp {
background-position: -39px -413px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_visibility_white_24dp {
background-position: -73px -413px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_wallet_giftcard_white_24dp {
background-position: -107px -413px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_wallet_membership_white_24dp {
background-position: -141px -413px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_wallet_travel_white_24dp {
background-position: -175px -413px;
width: 24px;
height: 24px;
}
.icon-action-white-ic_work_white_24dp {
background-position: -209px -413px;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,208 @@
.icon-content-white {
background-image: url('/static/images/css/sprite-content-white.png');
}
.icon-content-white-ic_inbox_white_24dp {
background-position: -5px -5px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_add_box_white_24dp {
background-position: -39px -5px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_add_circle_white_24dp {
background-position: -5px -39px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_add_white_24dp {
background-position: -39px -39px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_archive_white_24dp {
background-position: -73px -5px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_backspace_white_24dp {
background-position: -73px -39px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_block_white_24dp {
background-position: -5px -73px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_clear_white_24dp {
background-position: -39px -73px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_content_copy_white_24dp {
background-position: -73px -73px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_content_cut_white_24dp {
background-position: -107px -5px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_content_paste_white_24dp {
background-position: -107px -39px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_create_white_24dp {
background-position: -107px -73px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_drafts_white_24dp {
background-position: -5px -107px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_filter_list_white_24dp {
background-position: -39px -107px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_flag_white_24dp {
background-position: -73px -107px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_forward_white_24dp {
background-position: -107px -107px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_gesture_white_24dp {
background-position: -141px -5px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_add_circle_outline_white_24dp {
background-position: -141px -39px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_link_white_24dp {
background-position: -141px -73px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_mail_white_24dp {
background-position: -141px -107px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_markunread_white_24dp {
background-position: -5px -141px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_redo_white_24dp {
background-position: -39px -141px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_remove_circle_outline_white_24dp {
background-position: -73px -141px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_remove_circle_white_24dp {
background-position: -107px -141px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_remove_white_24dp {
background-position: -141px -141px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_reply_all_white_24dp {
background-position: -175px -5px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_reply_white_24dp {
background-position: -175px -39px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_report_white_24dp {
background-position: -175px -73px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_save_white_24dp {
background-position: -175px -107px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_select_all_white_24dp {
background-position: -175px -141px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_send_white_24dp {
background-position: -5px -175px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_sort_white_24dp {
background-position: -39px -175px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_text_format_white_24dp {
background-position: -73px -175px;
width: 24px;
height: 24px;
}
.icon-content-white-ic_undo_white_24dp {
background-position: -107px -175px;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,130 @@
.icon-navigation-white {
background-image: url('/static/images/css/sprite-navigation-white.png');
}
.icon-navigation-white-ic_close_white_24dp {
background-position: -5px -5px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_apps_white_24dp {
background-position: -39px -5px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_arrow_drop_down_circle_white_24dp {
background-position: -5px -39px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_arrow_drop_down_white_24dp {
background-position: -39px -39px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_arrow_drop_up_white_24dp {
background-position: -73px -5px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_arrow_forward_white_24dp {
background-position: -73px -39px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_cancel_white_24dp {
background-position: -5px -73px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_check_white_24dp {
background-position: -39px -73px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_chevron_left_white_24dp {
background-position: -73px -73px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_chevron_right_white_24dp {
background-position: -107px -5px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_arrow_back_white_24dp {
background-position: -107px -39px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_expand_less_white_24dp {
background-position: -107px -73px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_expand_more_white_24dp {
background-position: -5px -107px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_fullscreen_exit_white_24dp {
background-position: -39px -107px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_fullscreen_white_24dp {
background-position: -73px -107px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_menu_white_24dp {
background-position: -107px -107px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_more_horiz_white_24dp {
background-position: -141px -5px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_more_vert_white_24dp {
background-position: -141px -39px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_refresh_white_24dp {
background-position: -141px -73px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_unfold_less_white_24dp {
background-position: -141px -107px;
width: 24px;
height: 24px;
}
.icon-navigation-white-ic_unfold_more_white_24dp {
background-position: -5px -141px;
width: 24px;
height: 24px;
}

View File

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

18
site/static/js/default.js Normal file
View File

@ -0,0 +1,18 @@
$(document).ready(function(){
$('.ajaxPopup, .ajax-form').on('click', function(e){
e.preventDefault();
$.ajax({
url: $(this).attr('href'),
context: document.body
}).done(function(html) {
$( this ).addClass( "done" );
$('#ajaxPopup > div.content').html(html);
$('#ajaxPopup').show();
});
});
$('.closePopup').on('click', function(e){
e.preventDefault();
$('#ajaxPopup').hide();
});
});

4
site/static/js/jquery-2.1.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

View File

View File

@ -0,0 +1 @@
Please follow the link below to change your password.

0
site/tools/__init__.py Normal file
View File

View File

@ -0,0 +1,23 @@
import os
import sys
sys.path.append(os.path.abspath('../'))
from urlparse import urlparse
from StringIO import StringIO
from PIL import Image
import requests
from libs.rss_fetcher import feed_reader
import constants as site
feed = feed_reader(site.rss_feeds)
feed.enable_date_filter = False
count = 0
for row in feed:
full_url = row.get('image')
if full_url:
url = urlparse(full_url)
ext = os.path.split(url.path)[-1].split('.')[-1]
img = requests.get(full_url)
i = Image.open(StringIO(img.content))
i.save('images/blog_image_%s.%s' % (str(count), ext))
count += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Some files were not shown because too many files have changed in this diff Show More