Browse code
Many core features working
- TODO: implement subscriptions
fiddlerwoaroof authored on 15/03/2015 01:07:23Showing 18 changed files
- .gitignore
- db/.data.sql.swp
- db/.schema.sql.swp
- db/data.sql
- db/schema.sql
- sample_data/sites.json
- src/main.py
- src/marrow/.bone.py.swp
- src/marrow/.database.py.swp
- src/marrow/.user.py.swp
- src/marrow/__init__.py
- src/marrow/bone.py
- src/marrow/database.py
- src/marrow/user.py
- static/css/main.css
- static/index.html
- static/js/models.js
- static/robots.txt
10 | 15 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,31 @@ |
1 |
+INSERT INTO users (name, password, email) VALUES |
|
2 |
+ ('user1', 'password', 'user1@example.com'), |
|
3 |
+ ('user2', 'password', 'user2@example.com'), |
|
4 |
+ ('user3', 'password', 'user2@example.com'), |
|
5 |
+ ('user4', 'password', 'user2@example.com'), |
|
6 |
+ ('user5', 'password', 'user2@example.com'), |
|
7 |
+ ('user6', 'password', 'user2@example.com'), |
|
8 |
+ ('user7', 'password', 'user2@example.com'), |
|
9 |
+ ('user8', 'password', 'user2@example.com'); |
|
10 |
+ |
|
11 |
+SELECT * FROM put_link('user1', 'http://arguendo.com/this/is-link'); |
|
12 |
+SELECT * FROM put_link('user1', 'http://example.com/this/is-a-link'); |
|
13 |
+SELECT * FROM put_link('user1', 'http://google.com/is/is-a-link'); |
|
14 |
+SELECT * FROM put_link('user2', 'http://arguendo.com/this/is-link'); |
|
15 |
+SELECT * FROM put_link('user2', 'http://arguendo.com/this/is-link?a=we&b=34534'); |
|
16 |
+SELECT * FROM put_link('user2', 'http://example.com/this/is-a-link'); |
|
17 |
+SELECT * FROM put_link('user2', 'http://google.com/is/is-a-link'); |
|
18 |
+SELECT * FROM put_link('user3', 'http://arguendo.com/this/is-link'); |
|
19 |
+SELECT * FROM put_link('user3', 'http://arguendo.com/this/is-link?a=we&b=34534'); |
|
20 |
+SELECT * FROM put_link('user3', 'http://example.com/this/is-a-link'); |
|
21 |
+SELECT * FROM put_link('user3', 'http://google.com/is/is-a-link'); |
|
22 |
+SELECT * FROM put_link('user4', 'http://arguendo.com/this/is-link?a=we&b=34534'); |
|
23 |
+SELECT * FROM put_link('user5', 'http://arguendo.com/this/is-link?a=we&b=34534'); |
|
24 |
+SELECT * FROM put_link('user5', 'http://facebook.com'); |
|
25 |
+SELECT * FROM put_link('user5', 'http://google.com/is/is-a-link'); |
|
26 |
+SELECT * FROM put_link('user5', 'http://learn.knockoutjs.com/#/?tutorial=webmail'); |
|
27 |
+SELECT * FROM put_link('user5', 'http://python.org'); |
|
28 |
+SELECT * FROM put_link('user6', 'http://learn.knockoutjs.com/#/?tutorial=webmail'); |
|
29 |
+SELECT * FROM put_link('user6', 'http://stackoverflow.com/questions/13715743/psycopg2-not-actually-inserting-data'); |
|
30 |
+SELECT * FROM put_link('user7', 'http://learn.knockoutjs.com/#/?tutorial=webmail'); |
|
31 |
+SELECT * FROM put_link('user7', 'https://mail.google.com/mail/u/3/#inbox'); |
0 | 32 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,64 @@ |
1 |
+DROP TABLE IF EXISTS user_links; |
|
2 |
+DROP TABLE IF EXISTS users; |
|
3 |
+CREATE TABLE users ( |
|
4 |
+ id SERIAL UNIQUE NOT NULL, |
|
5 |
+ name TEXT UNIQUE NOT NULL, |
|
6 |
+ password TEXT NOT NULL, |
|
7 |
+ email TEXT NOT NULL, |
|
8 |
+ PRIMARY KEY (id) |
|
9 |
+); |
|
10 |
+ |
|
11 |
+DROP TABLE IF EXISTS links; |
|
12 |
+CREATE TABLE links ( |
|
13 |
+ id SERIAL UNIQUE NOT NULL, |
|
14 |
+ url TEXT NOT NULL, |
|
15 |
+ title TEXT DEFAULT '', |
|
16 |
+ posted TIMESTAMP DEFAULT current_timestamp, |
|
17 |
+ PRIMARY KEY (id) |
|
18 |
+); |
|
19 |
+CREATE INDEX url_index ON links (url); |
|
20 |
+ |
|
21 |
+CREATE TABLE user_links ( |
|
22 |
+ id SERIAL UNIQUE NOT NULL, |
|
23 |
+ user_id INTEGER REFERENCES users (id) NOT NULL, |
|
24 |
+ link_id INTEGER REFERENCES links (id) NOT NULL, |
|
25 |
+ UNIQUE (user_id, link_id), |
|
26 |
+ PRIMARY KEY (id) |
|
27 |
+); |
|
28 |
+ |
|
29 |
+DROP FUNCTION IF EXISTS get_bone(text); |
|
30 |
+CREATE OR REPLACE FUNCTION get_bone(username text) |
|
31 |
+ RETURNS TABLE(name text, url text, title text, posted timestamp) AS $$ |
|
32 |
+BEGIN |
|
33 |
+ RETURN QUERY SELECT users.name, links.url, links.title, links.posted |
|
34 |
+ FROM users |
|
35 |
+ INNER JOIN user_links ON user_links.user_id = users.id |
|
36 |
+ INNER JOIN links ON user_links.link_id = links.id |
|
37 |
+ WHERE users.name=username |
|
38 |
+ ORDER BY links.posted DESC; |
|
39 |
+END |
|
40 |
+$$ LANGUAGE plpgsql; |
|
41 |
+ |
|
42 |
+DROP FUNCTION IF EXISTS put_link(text,text,text); |
|
43 |
+DROP TYPE IF EXISTS link_url_type; |
|
44 |
+ |
|
45 |
+CREATE TYPE link_url_type AS (link_id int, user_id int); |
|
46 |
+CREATE OR REPLACE FUNCTION put_link(username text, link_url text, link_title text default '') |
|
47 |
+ RETURNS link_url_type |
|
48 |
+AS $$ |
|
49 |
+DECLARE |
|
50 |
+ n_link_id int; |
|
51 |
+ n_user_id int; |
|
52 |
+ result link_url_type; |
|
53 |
+BEGIN |
|
54 |
+ INSERT INTO links (url, title) VALUES |
|
55 |
+ (link_url, link_title) RETURNING id INTO n_link_id; |
|
56 |
+ SELECT users.id FROM users WHERE users.name = username INTO n_user_id; |
|
57 |
+ INSERT INTO user_links (user_id, link_id) VALUES (n_user_id, n_link_id); |
|
58 |
+ |
|
59 |
+ SELECT n_link_id INTO result.link_id; |
|
60 |
+ SELECT n_user_id INTO result.user_id; |
|
61 |
+ RETURN result; |
|
62 |
+END |
|
63 |
+$$ LANGUAGE plpgsql; |
|
64 |
+ |
... | ... |
@@ -1,14 +1,10 @@ |
1 |
-[ |
|
2 |
- {'url': 'http://www.wsj.com/articles/hillary-seems-tired-not-hungry-1426205650', |
|
3 |
- 'title': 'Hillary Seems Tired, Not Hungry', |
|
4 |
- 'short-url': 'http://themarrow.is/hillary-seems-tired'}, |
|
5 |
- {'url': 'http://www.wsj.com/articles/hillary-seems-tired-not-hungry-1426205650', |
|
6 |
- 'title': 'Hillary Seems Tired, But Capable', |
|
7 |
- 'short-url': 'http://themarrow.is/hillary-seems-tired-but'}, |
|
8 |
- {'url': 'http://example.com/some-page', |
|
9 |
- 'title': 'The Page Title', |
|
10 |
- 'short-url': 'http://themarrow.is/the-page-title'}, |
|
11 |
- {'url': 'http://example.com/another-page', |
|
12 |
- 'title': 'The Second Page Title', |
|
13 |
- 'short-url': 'http://themarrow.is/the-second-page'} |
|
14 |
-] |
|
1 |
+{"user1": [ |
|
2 |
+ {"url": "http://www.wsj.com/articles/hillary-seems-tired-not-hungry-1426205650", |
|
3 |
+ "title": "Hillary Seems Tired, Not Hungry"} |
|
4 |
+ {"url": "http://www.wsj.com/articles/hillary-seems-tired-not-hungry-1426205650", |
|
5 |
+ "title": "Hillary Seems Tired, But Capable"} |
|
6 |
+ {"url": "http://example.com/some-page", |
|
7 |
+ "title": "The Page Title"}, |
|
8 |
+ {"url": "http://example.com/another-page", |
|
9 |
+ "title": "The Second Page Title"} |
|
10 |
+]} |
... | ... |
@@ -1,14 +1,31 @@ |
1 |
-from flask import Flask, session, redirect, url_for, escape, request, abort |
|
1 |
+from flask import Flask, session, redirect, url_for, escape, request, abort, g |
|
2 | 2 |
import json |
3 |
+import os |
|
4 |
+import base64 |
|
5 |
+import psycopg2 |
|
6 |
+ |
|
7 |
+from marrow import database |
|
8 |
+from marrow import user |
|
9 |
+from marrow import bone |
|
3 | 10 |
|
4 | 11 |
app = Flask(__name__) |
12 |
+app.teardown_appcontext(database.close_connection) |
|
5 | 13 |
app.config["APPLICATION_ROOT"] = "/api" |
14 |
+app.secret_key = base64.b64encode(os.urandom(24)) |
|
15 |
+app.debug = True |
|
16 |
+ |
|
17 |
+ |
|
18 |
+# Blueprints # |
|
19 |
+user.get_users(app) |
|
20 |
+app.register_blueprint(user.user_blueprint, url_prefix='/user') |
|
21 |
+app.register_blueprint(bone.bone_blueprint, url_prefix='/bones') |
|
22 |
+ |
|
6 | 23 |
|
7 | 24 |
links = {} |
8 | 25 |
def get_feeds(filename): |
9 | 26 |
global links |
10 | 27 |
with open(filename) as f: |
11 |
- links = {'everyone': json.load(f)} |
|
28 |
+ links = json.load(f) |
|
12 | 29 |
|
13 | 30 |
@app.route('/') |
14 | 31 |
def index(): |
... | ... |
@@ -18,84 +35,5 @@ def index(): |
18 | 35 |
def humans(): |
19 | 36 |
return 'blah' |
20 | 37 |
|
21 |
-@app.route('/data/submit', methods=['POST']) |
|
22 |
-def submit_link(): |
|
23 |
- result = False |
|
24 |
- if 'username' in session: |
|
25 |
- obj = request.get_json() |
|
26 |
- links.setdefault(session['username'], []).append(dict( |
|
27 |
- title = obj.get('title',''), #TODO: get title somehow . . . |
|
28 |
- url = obj['url'] |
|
29 |
- )) |
|
30 |
- result = True |
|
31 |
- return json.dumps(result) |
|
32 |
- |
|
33 |
-@app.route('/data/<username>') |
|
34 |
-def user_data(username): |
|
35 |
- return json.dumps(links.get(username, [])) |
|
36 |
- |
|
37 |
-@app.route('/data',methods=['GET']) |
|
38 |
-def data(): |
|
39 |
- result = {'marrow':[]} |
|
40 |
- if 'username' in session: |
|
41 |
- result['marrow'] = links.get(session['username']) |
|
42 |
- else: |
|
43 |
- result['marrow'] = links['everyone'] |
|
44 |
- return json.dumps(result) |
|
45 |
- |
|
46 |
-users = {} |
|
47 |
-def get_users(filename): |
|
48 |
- global users |
|
49 |
- with open(filename) as f: |
|
50 |
- users = {x['username']:x for x in json.load(f)} |
|
51 |
- |
|
52 |
- |
|
53 |
-@app.route('/user/add', methods=['GET', 'POST']) |
|
54 |
-def adduser(): |
|
55 |
- if request.method == 'POST': |
|
56 |
- users[request.form['username']] = dict(username=request.form['username'], |
|
57 |
- password=request.form['password']) |
|
58 |
- return redirect(url_for('index')) |
|
59 |
- else: |
|
60 |
- return '''<form action="" method="post"><p> |
|
61 |
- <input type=text name=username> |
|
62 |
- <input type=text name=password> |
|
63 |
- <p><input type=submit value='Add User'></form>''' |
|
64 |
- |
|
65 |
-@app.route('/user/check') |
|
66 |
-def checkuser(): |
|
67 |
- return json.dumps('username' in session) |
|
68 |
- |
|
69 |
-@app.route('/login', methods=['GET', 'POST']) |
|
70 |
-def login(): |
|
71 |
- if request.method == 'POST': |
|
72 |
- username, password = request.form['username'], request.form['password'] |
|
73 |
- user = users.get(username, {}) |
|
74 |
- rightPassword = user.get(password,None) |
|
75 |
- if password == rightPassword: |
|
76 |
- session['username'] = request.form['username'] |
|
77 |
- else: |
|
78 |
- abort(403) |
|
79 |
- to = request.args.get('to', '/') |
|
80 |
- return redirect(to) |
|
81 |
- else: |
|
82 |
- return '''<form action="" method="post"><p> |
|
83 |
- <label for=username>User:</label> |
|
84 |
- <input type=text name=username> |
|
85 |
- <label for=password>Passwod:</label> |
|
86 |
- <input type=text name=password> |
|
87 |
- <p><input type=submit value=Login></form>''' |
|
88 |
- |
|
89 |
-@app.route('/logout') |
|
90 |
-def logout(): |
|
91 |
- session.pop('username', None) |
|
92 |
- return redirect(url_for('index')) |
|
93 |
- |
|
94 |
- |
|
95 |
-app.secret_key = 'Rp7ZKSO21AUDz6DUdROxVoWlZdUoGciX' |
|
96 |
- |
|
97 |
-get_users('sample_data/users.json') |
|
98 |
-get_feeds('sample_data/sites.json') |
|
99 |
-app.debug = True |
|
100 | 38 |
if __name__ == '__main__': |
101 | 39 |
app.run(host='0.0.0.0') |
109 | 47 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,51 @@ |
1 |
+import flask |
|
2 |
+from flask import Blueprint, session, redirect, url_for, escape, request, abort, g |
|
3 |
+from . import database |
|
4 |
+import json |
|
5 |
+ |
|
6 |
+bone_blueprint = Blueprint('bone', __name__) |
|
7 |
+ |
|
8 |
+@bone_blueprint.route('/submit', methods=['POST']) |
|
9 |
+def submit_link(): |
|
10 |
+ result = False |
|
11 |
+ if 'username' in session: |
|
12 |
+ obj = request.get_json() |
|
13 |
+ url, title = obj['url'],obj['title'] |
|
14 |
+ username = session['username'] |
|
15 |
+ db = database.get_db() |
|
16 |
+ with db.cursor() as cur: |
|
17 |
+ cur.callproc('put_link', (username, url, title)) |
|
18 |
+ cur.fetchall() |
|
19 |
+ if cur.rowcount != -1: |
|
20 |
+ db.commit() |
|
21 |
+ result = True |
|
22 |
+ return json.dumps(result) |
|
23 |
+ |
|
24 |
+@bone_blueprint.route('',defaults={'username':None}, methods=['GET']) |
|
25 |
+@bone_blueprint.route('/<username>', methods=['GET']) |
|
26 |
+def data(username): |
|
27 |
+ if username is None and 'username' in session: |
|
28 |
+ username = session['username'] |
|
29 |
+ |
|
30 |
+ result = {'marrow':[]} |
|
31 |
+ with database.get_db().cursor() as cur: |
|
32 |
+ cur.execute("SELECT url, title, posted from get_bone(%s);", (username,)) |
|
33 |
+ result['marrow'] = [ |
|
34 |
+ dict(url=url,title=title,posted=posted.isoformat()) |
|
35 |
+ for url,title,posted |
|
36 |
+ in cur.fetchall() |
|
37 |
+ ] |
|
38 |
+ return json.dumps(result) |
|
39 |
+ |
|
40 |
+import random |
|
41 |
+@bone_blueprint.route('/random') |
|
42 |
+def random(): |
|
43 |
+ db = database.get_db() |
|
44 |
+ with db.cursor() as cur: |
|
45 |
+ if 'username' in session: |
|
46 |
+ cur.execute('SELECT name FROM users WHERE name != %s ORDER BY random() LIMIT 1', |
|
47 |
+ (session['username'],)) |
|
48 |
+ else: |
|
49 |
+ cur.execute('SELECT name FROM users ORDER BY random() LIMIT 1') |
|
50 |
+ username = cur.fetchone()[0] |
|
51 |
+ return redirect(url_for('bone.data', username=username)) |
0 | 52 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,20 @@ |
1 |
+from flask import g |
|
2 |
+import psycopg2 |
|
3 |
+ |
|
4 |
+def get_db(): |
|
5 |
+ db = getattr(g, '_database', None) |
|
6 |
+ if db is None: |
|
7 |
+ db = g._database = psycopg2.connect( |
|
8 |
+ database="marrow", |
|
9 |
+ user="marrow", |
|
10 |
+ password="marrowpass", |
|
11 |
+ host="pgsqlserver.elangley.org" |
|
12 |
+ ); |
|
13 |
+ return db |
|
14 |
+ |
|
15 |
+def close_connection(exception): |
|
16 |
+ db = getattr(g, '_database', None) |
|
17 |
+ if db is not None: |
|
18 |
+ db.close() |
|
19 |
+ |
|
20 |
+ |
0 | 21 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,68 @@ |
1 |
+import flask |
|
2 |
+from flask import Blueprint, session, redirect, url_for, escape, request, abort, g |
|
3 |
+from . import database |
|
4 |
+import json |
|
5 |
+ |
|
6 |
+user_blueprint = Blueprint('user', __name__) |
|
7 |
+ |
|
8 |
+users = {} |
|
9 |
+def get_users(app): |
|
10 |
+ with app.app_context(): _get_users() |
|
11 |
+ |
|
12 |
+def _get_users(): |
|
13 |
+ global users |
|
14 |
+ cur = database.get_db().cursor() |
|
15 |
+ with cur: |
|
16 |
+ cur.execute('SELECT name,password,email FROM users') |
|
17 |
+ for username,password,email in cur.fetchall(): |
|
18 |
+ users[username] = dict(username=username, password=password, email=email) |
|
19 |
+ |
|
20 |
+#TODO: load this from somewhere |
|
21 |
+user_env = {} |
|
22 |
+@user_blueprint.route('/environment') |
|
23 |
+def get_user_env(): |
|
24 |
+ if 'username' in session: |
|
25 |
+ username = session['username'] |
|
26 |
+ env = user_env.setdefault(username, {}) |
|
27 |
+ env['username'] = username |
|
28 |
+ return env |
|
29 |
+ |
|
30 |
+@user_blueprint.route('/list') |
|
31 |
+def list_users(): |
|
32 |
+ return json.dumps([_ for _ in users.keys()]) |
|
33 |
+ |
|
34 |
+@user_blueprint.route('/add', methods=['POST']) |
|
35 |
+def adduser(): |
|
36 |
+ db = database.get_db() |
|
37 |
+ with db.cursor() as cur: |
|
38 |
+ obj = request.get_json(); |
|
39 |
+ username, password = obj['username'], obj['password'] |
|
40 |
+ cur.execute('INSERT INTO users (name,password,email) VALUES (%s,%s,%s)', |
|
41 |
+ (username, password, 'abc@def.com')) |
|
42 |
+ _get_users() |
|
43 |
+ db.commit() |
|
44 |
+ session['username'] = username |
|
45 |
+ return json.dumps(True) |
|
46 |
+ |
|
47 |
+@user_blueprint.route('/check') |
|
48 |
+def checkuser(): |
|
49 |
+ return json.dumps('username' in session) |
|
50 |
+ |
|
51 |
+@user_blueprint.route('/login', methods=['POST']) |
|
52 |
+def login(): |
|
53 |
+ obj = request.get_json(); |
|
54 |
+ result = False |
|
55 |
+ username, password = obj['username'], obj['password'] |
|
56 |
+ user = users.get(username, {}) |
|
57 |
+ rightPassword = user.get('password',None) |
|
58 |
+ if password == rightPassword: |
|
59 |
+ session['username'] = username |
|
60 |
+ result = True |
|
61 |
+ return json.dumps(result) |
|
62 |
+ |
|
63 |
+@user_blueprint.route('/logout') |
|
64 |
+def logout(): |
|
65 |
+ to = request.args.get('to', '/') |
|
66 |
+ session.pop('username', None) |
|
67 |
+ return redirect(to) |
|
68 |
+ |
... | ... |
@@ -48,13 +48,31 @@ a { |
48 | 48 |
text-decoration: none; |
49 | 49 |
} |
50 | 50 |
|
51 |
+.hidden { |
|
52 |
+ display: none; |
|
53 |
+} |
|
54 |
+ |
|
55 |
+#login_form { |
|
56 |
+ z-index: 100; |
|
57 |
+ background: white; |
|
58 |
+ position: absolute; |
|
59 |
+ height:100%; |
|
60 |
+ width:100%; |
|
61 |
+ top: 0px; |
|
62 |
+ left: 0px; |
|
63 |
+} |
|
64 |
+#login_form form { |
|
65 |
+ position: absolute; |
|
66 |
+ top:25%; |
|
67 |
+ left:25%; |
|
68 |
+} |
|
69 |
+ |
|
51 | 70 |
#sidebar{ |
52 | 71 |
position: absolute; |
53 | 72 |
height: 25%; |
54 | 73 |
width: 10%; |
55 | 74 |
top: 37.5%; |
56 | 75 |
left: 0px; |
57 |
- background: #aaa; |
|
58 | 76 |
} |
59 | 77 |
|
60 | 78 |
#sidebar ul { |
... | ... |
@@ -68,14 +86,18 @@ a { |
68 | 86 |
padding-bottom: 5px; |
69 | 87 |
} |
70 | 88 |
|
71 |
- |
|
72 |
- |
|
73 | 89 |
#main{ |
90 |
+ padding-left: 10px; |
|
91 |
+ padding-top: 50px; |
|
74 | 92 |
position: absolute; |
75 | 93 |
height:100%; |
76 | 94 |
top:0px; |
77 | 95 |
right:0px; |
78 | 96 |
width: 90%; |
79 |
- background: #bbb; |
|
80 |
- |
|
81 | 97 |
} |
98 |
+ |
|
99 |
+#main ul { |
|
100 |
+ position:relative; |
|
101 |
+} |
|
102 |
+ |
|
103 |
+#main ul |
... | ... |
@@ -7,6 +7,15 @@ |
7 | 7 |
<link rel="stylesheet" href="/css/main.css" media="screen" /> |
8 | 8 |
</head> |
9 | 9 |
<body> |
10 |
+ <div id="login_form"> |
|
11 |
+ <div class="message"></div> |
|
12 |
+ <form data-bind="submit: login.login"> |
|
13 |
+ <input type="text" name="username" placeholder="Username" data-bind="value: login.username" /> |
|
14 |
+ <input type="text" name="password" placeholder="Password" data-bind="value: login.password" /> |
|
15 |
+ <button type="submit" >Log In</button> |
|
16 |
+ <button data-bind="click: login.newuser">Add User</button> |
|
17 |
+ </form> |
|
18 |
+ </div> |
|
10 | 19 |
<div class="container"> |
11 | 20 |
<section id="main"> |
12 | 21 |
<ul data-bind='foreach: marrow'> |
... | ... |
@@ -21,7 +30,8 @@ |
21 | 30 |
<ul> |
22 | 31 |
<li><a href="/">Home</a></li> |
23 | 32 |
<li><a href="/mylists">My Lists</a></li> |
24 |
- <li><a href="/random">Random</a></li> |
|
33 |
+ <li><a href="#" data-bind="click: random">Random</a></li> |
|
34 |
+ <li><a href="/api/user/logout?to=/">Log Out</a></li> |
|
25 | 35 |
</ul> |
26 | 36 |
</section> |
27 | 37 |
</div> |
... | ... |
@@ -5,21 +5,91 @@ function Marrow(data) { |
5 | 5 |
this.url = ko.observable(data.url); |
6 | 6 |
}; |
7 | 7 |
|
8 |
+function Login(master) { |
|
9 |
+ var self = this; |
|
10 |
+ self.username = ko.observable(); |
|
11 |
+ self.password = ko.observable(); |
|
12 |
+ |
|
13 |
+ self.check = function() { |
|
14 |
+ $.getJSON("/api/user/check", function (logged_in) { |
|
15 |
+ if (logged_in) { |
|
16 |
+ master.update(function() { |
|
17 |
+ $('#login_form').addClass('hidden'); |
|
18 |
+ }); |
|
19 |
+ } |
|
20 |
+ }); |
|
21 |
+ }; |
|
22 |
+ |
|
23 |
+ self.login = function() { |
|
24 |
+ var username = self.username(); |
|
25 |
+ var password = self.password(); |
|
26 |
+ $.ajax("/api/user/login", { |
|
27 |
+ data: ko.toJSON({username:username,password:password}), |
|
28 |
+ type: "post", contentType: "application/json", |
|
29 |
+ success: function(login_succeeded) { |
|
30 |
+ login_succeeded = JSON.parse(login_succeeded); |
|
31 |
+ console.log(login_succeeded); |
|
32 |
+ var login_form = $('#login_form'); |
|
33 |
+ if (login_succeeded === true) { |
|
34 |
+ master.update(function() { |
|
35 |
+ login_form.addClass('hidden'); |
|
36 |
+ }); |
|
37 |
+ } else { |
|
38 |
+ login_form.children('.message').text('Login Failed!').addClass('err'); |
|
39 |
+ } |
|
40 |
+ |
|
41 |
+ } |
|
42 |
+ }); |
|
43 |
+ }; |
|
44 |
+ |
|
45 |
+ self.newuser = function() { |
|
46 |
+ var username = self.username(); |
|
47 |
+ var password = self.password(); |
|
48 |
+ $.ajax("/api/user/add", { |
|
49 |
+ data: ko.toJSON({username:username,password:password}), |
|
50 |
+ type: "post", contentType: "application/json", |
|
51 |
+ success: function(creation_succeeded) { |
|
52 |
+ creation_succeeded = JSON.parse(creation_succeeded); |
|
53 |
+ console.log(creation_succeeded); |
|
54 |
+ if (creation_succeeded === true) { |
|
55 |
+ $('#login_form').addClass('hidden'); |
|
56 |
+ } |
|
57 |
+ } |
|
58 |
+ }); |
|
59 |
+ }; |
|
60 |
+}; |
|
61 |
+ |
|
8 | 62 |
function Bone() { |
9 | 63 |
var self = this; |
10 | 64 |
self.marrow = ko.observableArray([]); |
11 | 65 |
self.newLink = ko.observable(); |
66 |
+ self.login = new Login(self); |
|
67 |
+ self.login.check(); |
|
12 | 68 |
|
13 | 69 |
self.add_marrow = function(link) {}; |
14 | 70 |
|
15 |
- $.getJSON("/api/data", function(data) { |
|
16 |
- var otherMarrow = $.map(data.marrow, function(item) { return new Marrow(item) }); |
|
17 |
- self.marrow(otherMarrow); |
|
18 |
- }); |
|
71 |
+ self.random = function() { |
|
72 |
+ $.getJSON("/api/bones/random", function(data) { |
|
73 |
+ if (data !== []) { |
|
74 |
+ var theMarrow = $.map(data.marrow, function(item) { return new Marrow(item) }); |
|
75 |
+ self.marrow(theMarrow); |
|
76 |
+ } |
|
77 |
+ }); |
|
78 |
+ }; |
|
79 |
+ |
|
80 |
+ self.update = function(cb) { |
|
81 |
+ $.getJSON("/api/bones", function(data) { |
|
82 |
+ if (data !== []) { |
|
83 |
+ var theMarrow = $.map(data.marrow, function(item) { return new Marrow(item) }); |
|
84 |
+ self.marrow(theMarrow); |
|
85 |
+ } |
|
86 |
+ cb(); |
|
87 |
+ }); |
|
88 |
+ }; |
|
19 | 89 |
|
20 | 90 |
self.addLink = function() { |
21 | 91 |
var newLink = {url:self.newLink(),title:''}; |
22 |
- $.ajax("/api/data/submit", { |
|
92 |
+ $.ajax("/api/bones/submit", { |
|
23 | 93 |
data: ko.toJSON(newLink), |
24 | 94 |
type: "post", contentType: "application/json", |
25 | 95 |
success: function(result) { |