Download:
child 8:39ac2486b9d3
parent 6:2a4d20de1da1
7:5c5d433b3a14
Anton Shestakov <engored@ya.ru>, Thu, 27 Dec 2012 00:12:30 +0900
Moving toward a multi-workspace work model. There's no auth, knowing workspace id gives full access.

8 файлов изменено, 77 вставок(+), 50 удалений(-) [+]
app.py file | annotate | diff | comparison | revisions
fruitbar/indexes.py file | annotate | diff | comparison | revisions
static/js/framework/collections.js file | annotate | diff | comparison | revisions
static/js/framework/models.js file | annotate | diff | comparison | revisions
static/js/framework/router.js file | annotate | diff | comparison | revisions
static/js/framework/views/projects.js file | annotate | diff | comparison | revisions
static/js/ui.js file | annotate | diff | comparison | revisions
templates/index.html file | annotate | diff | comparison | revisions
--- a/app.py Wed Dec 26 22:01:21 2012 +0900
+++ b/app.py Thu Dec 27 00:12:30 2012 +0900
@@ -26,9 +26,6 @@
cdb.add_index(ProjectIndex(cdb.path, 'project'))
cdb.add_index(TaskIndex(cdb.path, 'task'))
-
- cdb.insert({'_id': '29c21f00190f475ba2d855f810c1085e', '_t': 'project', 'name': 'Test Project', 'color': 'success'})
- cdb.insert({'_t': 'task', 'project': '29c21f00190f475ba2d855f810c1085e', 'name': 'Test Task', 'note': 'Task Note', 'done': True})
@app.before_request
@@ -40,12 +37,13 @@
db_index = 'id'
doc_stub = {}
- def get(self):
- return [project['doc'] for project in g.db.all(self.db_index, with_doc=True)]
+ def get(self, workspace):
+ return [project['doc'] for project in g.db.get_many(self.db_index, workspace, with_doc=True)]
- def post(self):
- doc = self.doc_stub.copy()
- doc.update(request.json)
+ def post(self, workspace):
+ doc = request.json.copy()
+ doc.update(self.doc_stub)
+ doc.update({'workspace': workspace})
response = g.db.insert(doc)
@@ -58,17 +56,23 @@
safe_fields = tuple()
- def get(self, resource_id):
+ def get(self, workspace, resource_id):
try:
doc = g.db.get('id', resource_id, with_doc=True)
+
+ if doc['workspace'] != workspace:
+ raise RecordNotFound
except RecordNotFound:
return '', 404
return doc
- def put(self, resource_id):
+ def put(self, workspace, resource_id):
try:
doc = g.db.get('id', resource_id, with_doc=True)
+
+ if doc['workspace'] != workspace:
+ raise RecordNotFound
except RecordNotFound:
return '', 404
@@ -76,11 +80,14 @@
doc.update(userdata)
response = g.db.update(doc)
- return self.get(response['_id'])
+ return self.get(workspace, response['_id'])
- def delete(self, resource_id):
+ def delete(self, workspace, resource_id):
try:
doc = g.db.get('id', resource_id, with_doc=True)
+
+ if doc['workspace'] != workspace:
+ raise RecordNotFound
except RecordNotFound:
return '', 404
@@ -97,10 +104,10 @@
class Project(CRUDResource):
safe_fields = ('name', 'color')
- def delete(self, resource_id):
- g.db.run('task', 'delete_for_project', resource_id)
+ def delete(self, workspace, resource_id):
+ g.db.run('task', 'delete_for_project', workspace, resource_id)
- return super(Project, self).delete(resource_id)
+ return super(Project, self).delete(workspace, resource_id)
class TaskList(ResourceList):
@@ -112,20 +119,15 @@
safe_fields = ('name', 'note', 'done')
-api.add_resource(ProjectList, '/projects/')
-api.add_resource(Project, '/projects/<resource_id>/')
-api.add_resource(TaskList, '/tasks/')
-api.add_resource(Task, '/tasks/<resource_id>/')
+api.add_resource(ProjectList, '/<workspace>/projects/')
+api.add_resource(Project, '/<workspace>/projects/<resource_id>/')
+api.add_resource(TaskList, '/<workspace>/tasks/')
+api.add_resource(Task, '/<workspace>/tasks/<resource_id>/')
@app.route('/')
def index():
- data = {
- 'projects': [project['doc'] for project in g.db.all('project', with_doc=True)],
- 'tasks': [task['doc'] for task in g.db.all('task', with_doc=True)]
- }
-
- return render_template('index.html', data=data)
+ return render_template('index.html')
def main():
--- a/fruitbar/indexes.py Wed Dec 26 22:01:21 2012 +0900
+++ b/fruitbar/indexes.py Thu Dec 27 00:12:30 2012 +0900
@@ -9,11 +9,11 @@
def __init__(self, *args, **kwargs):
kwargs['key_format'] = '16s'
super(ProjectIndex, self).__init__(*args, **kwargs)
-
+
def make_key_value(self, data):
if data['_t'] == 'project':
- return md5(data['name'].encode('utf-8')).digest(), None
-
+ return md5(data['workspace'].encode('utf-8')).digest(), None
+
def make_key(self, key):
return md5(key).digest()
@@ -22,15 +22,15 @@
def __init__(self, *args, **kwargs):
kwargs['key_format'] = '16s'
super(TaskIndex, self).__init__(*args, **kwargs)
-
+
def make_key_value(self, data):
if data['_t'] == 'task':
- return md5(data['project'].encode('utf-8')).digest(), None
-
+ return md5(data['workspace'].encode('utf-8')).digest(), None
+
def make_key(self, key):
return md5(key).digest()
- def run_delete_for_project(self, db, project):
- for task in db.get_many('task', project, with_doc=True):
- db.delete(task['doc'])
-
+ def run_delete_for_project(self, db, workspace, project_id):
+ for task in db.get_many('task', workspace, with_doc=True):
+ if task['doc']['project_id'] == project_id:
+ db.delete(task['doc'])
--- a/static/js/framework/collections.js Wed Dec 26 22:01:21 2012 +0900
+++ b/static/js/framework/collections.js Thu Dec 27 00:12:30 2012 +0900
@@ -1,9 +1,13 @@
var Projects = Backbone.Collection.extend({
model: Project,
- url: '/projects/'
+ url: function() {
+ return '/' + encodeURIComponent(fruitbar.workspace) + '/projects/';
+ }
});
var Tasks = Backbone.Collection.extend({
model: Task,
- url: '/tasks/'
+ url: function() {
+ return '/' + encodeURIComponent(fruitbar.workspace) + '/tasks/';
+ }
});
--- a/static/js/framework/models.js Wed Dec 26 22:01:21 2012 +0900
+++ b/static/js/framework/models.js Thu Dec 27 00:12:30 2012 +0900
@@ -7,7 +7,6 @@
adhoc: function(data) {
var model = this;
var options = {
- url: this.urlRoot + encodeURIComponent(this.id) + '/',
contentType: 'application/json',
data: JSON.stringify(data)
};
@@ -20,7 +19,6 @@
var Project = Model.extend({
idAttribute: '_id',
- urlRoot: '/projects/',
switchColor: function() {
var colorChain = [null, 'info', 'success', 'warning', 'danger'];
@@ -32,6 +30,5 @@
});
var Task = Model.extend({
- idAttribute: '_id',
- urlRoot: '/tasks/'
+ idAttribute: '_id'
});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/js/framework/router.js Thu Dec 27 00:12:30 2012 +0900
@@ -0,0 +1,24 @@
+var Router = Backbone.Router.extend({
+ routes: {
+ '': 'randomize',
+ ':workspace': 'setWorkspace'
+ },
+
+ makeRandomString: function(length) {
+ return _.map(_.range(length), function() {
+ return (Math.random()*16|0).toString(16);
+ }).join('');
+ },
+
+ randomize: function() {
+ var randomString = this.makeRandomString(8);
+ this.navigate(randomString, {trigger: true, replace: true});
+ },
+
+ setWorkspace: function(workspace) {
+ fruitbar.workspace = workspace;
+
+ fruitbar.tasks.fetch();
+ fruitbar.projects.fetch();
+ }
+});
--- a/static/js/framework/views/projects.js Wed Dec 26 22:01:21 2012 +0900
+++ b/static/js/framework/views/projects.js Thu Dec 27 00:12:30 2012 +0900
@@ -62,7 +62,7 @@
project.tasks = new Backbone.Shard({
collection: this.tasks,
- filter: function(task) { return task.get('project') === project.id; }
+ filter: function(task) { return task.get('project_id') === project.id; }
});
project.tasks.progress = function() {
@@ -71,7 +71,7 @@
project.tasks.create = function(attributes, options) {
attributes = attributes || {};
- attributes['project'] = project.id;
+ attributes['project_id'] = project.id;
return tasks.create(attributes, options);
};
--- a/static/js/ui.js Wed Dec 26 22:01:21 2012 +0900
+++ b/static/js/ui.js Thu Dec 27 00:12:30 2012 +0900
@@ -1,7 +1,8 @@
$(function() {
- window.fruitbar = {};
- fruitbar.tasks = new Tasks(data['tasks']);
- fruitbar.projects = new Projects(data['projects']);
+ window.fruitbar = {workspace: undefined};
+ fruitbar.tasks = new Tasks();
+ fruitbar.projects = new Projects();
+ fruitbar.router = new Router();
fruitbar.projectCounter = new CollectionCounterView({
el: $('.project-counter'),
@@ -21,6 +22,8 @@
}
});
+ Backbone.history.start();
+
window.setInterval(function() {fruitbar.projects.fetch({update: true});}, 60000);
window.setInterval(function() {fruitbar.tasks.fetch({update: true});}, 60000);
});
--- a/templates/index.html Wed Dec 26 22:01:21 2012 +0900
+++ b/templates/index.html Thu Dec 27 00:12:30 2012 +0900
@@ -18,6 +18,7 @@
<script type="text/javascript" src="{{ url_for('static', filename='js/framework/views/inline.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/framework/views/projects.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/framework/views/tasks.js') }}"></script>
+ <script type="text/javascript" src="{{ url_for('static', filename='js/framework/router.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/ui.js') }}"></script>
<script type="text/javascript">
@@ -96,9 +97,5 @@
</script>
</section>
</div>
-
- <script type="text/javascript">
- var data = {{ data|tojson|safe }};
- </script>
</body>
</html>