isfolded column, uuid instead of int for id

This commit is contained in:
2016-02-02 13:25:24 +08:00
parent 8678dd220b
commit 0c2e8179e2
12 changed files with 215 additions and 215 deletions
+3 -1
View File
@@ -22,7 +22,9 @@
"localforage-backbone": "~0.6.2",
"normalize-css": "normalize.css#~3.0.3",
"backbone.marionette": "~2.4.4",
"underscore": "~1.8.3"
"underscore": "~1.8.3",
"foundation-sites": "~6.1.2",
"foundation-icon-fonts": "*"
},
"resolutions": {
"jquery": "^1.8.0 || ^2.0.0"
+5 -4
View File
@@ -3,13 +3,14 @@ var Sequelize = require('sequelize');
module.exports = {
instance: function(orm) {
task = orm.define('Tasks', {
id : {type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true},
id : {type: Sequelize.UUID, primaryKey: true, defaultValue: Sequelize.UUIDV4,},
content : {type: Sequelize.TEXT, allowNull: false},
parentId : {type: Sequelize.INTEGER, defaultValue: 0},
parentId : {type: Sequelize.UUID, defaultValue: '00000000-0000-0000-0000-000000000000'},
isCompleted: {type: Sequelize.BOOLEAN, defaultValue: false},
priority : {type: Sequelize.INTEGER, defaultValue: 0},
createdAt : Sequelize.DATE,
updatedAt : Sequelize.DATE,
isFolded : {type: Sequelize.BOOLEAN, defaultValue: false},
createdAt : {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
updatedAt : {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
});
orm.sync();
+21 -4
View File
@@ -18,6 +18,22 @@ localforageBackbone
model: Task,
offlineSync: Backbone.localforage.sync("tasks"),
/** Override backbone parse **/
// parse: function(models){
// if (this._isModel(models))
// return models;
// var parsedModels =[];
// for (var i = 0; i < models.length; i++) {
// if (this._isModel(models[i]))
// parsedModels.push(models[i]);
// else
// parsedModels.push(new this.model(models[i]));
// }
// return parsedModels;
//
// },
initialize: function(){
// update order on add, remove.
// Ref: http://stackoverflow.com/a/11665085/221742
@@ -53,8 +69,9 @@ localforageBackbone
/** Updated priority of each member of list **/
updateModelPriority: function() {
this.each(function(model, index) {
if (model)
model.set('priority', index);
if (model && model.get('priority')!==index)
model.save({'priority': index});
}, this);
},
@@ -71,8 +88,8 @@ localforageBackbone
},
/** sort by priority then created date **/
comporator: function(child){
return [child.get('priority'), child.get('createdAt')];
comparator: function(child){
return [child.get('priority')];
},
url: '/tasks'
+112 -115
View File
@@ -1,115 +1,112 @@
define(function (require) {
return [{
"id": 80,
"content": "Welcome to HackFlowy!",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": 81,
"content": "An open-source WorkFlowy clone",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": 82,
"content": "Built using Backbone + Socket.IO",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": 83,
"content": "Pulled this together in a few hours to learn Backbone",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": 84,
"content": "Feel free to try it out and hack on it",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": 85,
"content": "Good Luck!",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": 86,
"content": "P.S",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:40.978Z",
"updatedAt": "2016-01-29T05:44:40.978Z"
}, {
"id": 88,
"content": "It makes sense if you don't think about it; I haven't",
"parentId": 0,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:44:58.737Z",
"updatedAt": "2016-01-29T05:45:50.939Z"
}, {
"id": 89,
"content": "Make love not war",
"parentId": 88,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:45:03.048Z",
"updatedAt": "2016-01-29T05:45:57.481Z"
}, {
"id": 91,
"content": "Love can be brought not sold",
"parentId": 88,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:45:32.331Z",
"updatedAt": "2016-01-29T05:46:10.478Z"
}, {
"id": 93,
"content": "How do I love thee? Let me count the ways - Shakespeare",
"parentId": 88,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:46:25.119Z",
"updatedAt": "2016-01-29T05:48:00.604Z"
}, {
"id": 95,
"content": "Therefore: love can be listed and lists can be loved",
"parentId": 88,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:46:38.998Z",
"updatedAt": "2016-01-29T05:48:22.937Z"
}, {
"id": 96,
"content": "Conclusion: lists and love should be free",
"parentId": 88,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:47:26.684Z",
"updatedAt": "2016-01-29T05:48:29.796Z"
}, {
"id": 97,
"content": "But how can our lists be real if our love isnt? - Jaden Smith",
"parentId": 88,
"isCompleted": false,
"priority": 0,
"createdAt": "2016-01-29T05:47:46.930Z",
"updatedAt": "2016-01-29T05:47:46.930Z"
}];
});
[{
"id": "fba0d0d9-d540-03c2-ecd5-cb5c391484ef",
"content": "Welcome to HackFlowy!",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 1,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": "886689fd-8ca1-75ed-8086-fe05904ff039",
"content": "An open-source WorkFlowy clone",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 2,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": "bbc8e79d-5e51-83b8-2639-812471972e04",
"content": "Built using Backbone + Socket.IO",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 3,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": "602f03a8-bfdd-5193-f0bb-b4d0f5fa165c",
"content": "Pulled this together in a few hours to learn Backbone",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 4,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": "1e663464-4c22-bd0a-85a7-3a287ac2f02e",
"content": "Feel free to try it out and hack on it",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 5,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": "d25704a8-fe09-ab2a-7c54-58c5e8113e88",
"content": "Good Luck!",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 6,
"createdAt": "2016-01-29T05:44:30.858Z",
"updatedAt": "2016-01-29T05:44:30.858Z"
}, {
"id": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
"content": "P.S",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 7,
"isFolded": true,
"createdAt": "2016-01-29T05:44:40.978Z",
"updatedAt": "2016-01-29T05:44:40.978Z"
}, {
"id": "70a84964-658d-fbf9-4552-e8f243138f6e",
"content": "It makes sense if you don't think about it; I haven't",
"parentId": "00000000-0000-0000-0000-000000000000",
"isCompleted": false,
"priority": 8,
"createdAt": "2016-01-29T05:44:58.737Z",
"updatedAt": "2016-01-29T05:45:50.939Z"
}, {
"id": 89,
"content": "Make love not war",
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
"isCompleted": false,
"priority": 1,
"createdAt": "2016-01-29T05:45:03.048Z",
"updatedAt": "2016-01-29T05:45:57.481Z"
}, {
"id": 91,
"content": "Love can be brought not sold",
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
"isCompleted": false,
"priority": 2,
"createdAt": "2016-01-29T05:45:32.331Z",
"updatedAt": "2016-01-29T05:46:10.478Z"
}, {
"id": 93,
"content": "How do I love thee? Let me count the ways - Shakespeare",
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
"isCompleted": false,
"priority": 3,
"createdAt": "2016-01-29T05:46:25.119Z",
"updatedAt": "2016-01-29T05:48:00.604Z"
}, {
"id": 95,
"content": "Therefore: love can be listed and lists can be loved",
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
"isCompleted": false,
"priority": 4,
"createdAt": "2016-01-29T05:46:38.998Z",
"updatedAt": "2016-01-29T05:48:22.937Z"
}, {
"content": "Conclusion: lists and love should be free",
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
"isCompleted": false,
"priority": 5,
"createdAt": "2016-01-29T05:47:26.684Z",
"updatedAt": "2016-01-29T05:48:29.796Z"
}, {
"content": "But how can our lists be real if our love isnt? - Jaden Smith",
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
"isCompleted": false,
"priority": 6,
"createdAt": "2016-01-29T05:47:46.930Z",
"updatedAt": "2016-01-29T05:47:46.930Z"
}]
+11 -9
View File
@@ -1,13 +1,13 @@
define(
['backbone',
'localforage',
'localforagebackbone'
],
function (
'localforagebackbone',
'util/constants',
],function (
Backbone,
localforage,
localforageBackbone
localforageBackbone,
constants
) {
var TaskModel = Backbone.Model.extend({
@@ -24,11 +24,12 @@ function (
},
defaults: {
parentId: 0,
parentId: constants.ROOT_PARENT_ID,
content: '',
isCompleted: 0,
isCompleted: false,
isFolded: false,
priority: 0,
id: '',
id: undefined,
},
toggelCompletedStatus: function (isCompleted) {
@@ -48,7 +49,8 @@ function (
},
focusOnView: function(){
return this.view.$('input:first').focus();
if (this.view && this.view.$el)
return this.view.$('input:first').focus();
}
});
+1
View File
@@ -4,6 +4,7 @@ define(
function() {
var constants = {
ROOT_PARENT_ID: '00000000-0000-0000-0000-000000000000',
ENTER_KEY :13,
UP_ARROW: 38,
-42
View File
@@ -31,48 +31,6 @@ define(
initialize: function () {
},
/** Get root id for the displayed list from the url hash or 0 **/
// getRootId: function(){
// var hash = window.location.hash.slice(1);
// return hash ? hash: 0;
//
// },
// /** Called when window location hash changes **/
// changeRootId: function(){
// this.collection.remove(this.collection.models);
// this.collection.add(pageView.collection.filter(this.filterDirectChildren,this));
// this.updateBreadCrumbs();
// },
// updateBreadCrumbs: function(){
// var rootId = this.getRootId();
// if (rootId){
// var current = Tasks.get(rootId);
// var breadCrumbs = _.template('<a href="#<%= id %>"><%= content %></a>')(current.attributes);
// var depth=0;
// while (current.get('parentId') && depth<100){
// depth++;
// current = Tasks.get(current.get('parentId'));
// breadCrumbs=_.template('<a href="#<%= id %>"><%= content %></a> > ')(current.attributes)+breadCrumbs;
// }
// if (depth>=100) console.error('Max depth exceeded while making breadCrumbs');
// breadCrumbs='<a href="#">Home</a> > '+breadCrumbs;
// $('#task-breadcrumbs').append(breadCrumbs);
//
// }
// },
// Only show direct children
// filterDirectChildren: function (child, index, collection) {
// var rootId = this.getRootId();
// if (rootId)
// return child.get('id') == rootId;
// else
// return child.get('parentId') == rootId;
// },
/** This is the root view in the tree **/
getParentView: function () {
return this;
+13 -10
View File
@@ -3,9 +3,10 @@ define(
'backbone',
'marionette',
'views/list',
'data/demo',
'text!data/demo.json',
'models/task',
'collections/list'
'collections/list',
'util/constants',
],
function(
@@ -15,7 +16,8 @@ Marionette,
ListView,
demoData,
Task,
List
List,
constants
) {
var PageView = Marionette.View.extend({
@@ -87,7 +89,7 @@ List
return hash;
else if (hash)
window.location.hash='';
return 0;
return constants.ROOT_PARENT_ID;
},
/** Called when window location hash changes **/
@@ -101,23 +103,24 @@ List
// Only show direct children
filterDirectChildren: function (child, index, collection) {
var rootId = this.getRootId();
if (rootId)
return child.get('id') == rootId;
if (rootId === constants.ROOT_PARENT_ID)
return child.get('parentId') === rootId;
else
return child.get('parentId') == rootId;
return child.get('id') == rootId;
},
updateBreadCrumbs: function(){
var rootId = this.getRootId();
this.$('#task-breadcrumbs').empty();
if (rootId){
if (rootId!==constants.ROOT_PARENT_ID){
var current = this.collection.get(rootId);
var breadCrumbs = '';//_.template('<a href="#<%= id %>"><%= content %></a>')(current.attributes);
var depth=0;
while (current.get('parentId') && depth<100){
while (current && current.get('parentId') && depth<100){
depth++;
current = this.collection.get(current.get('parentId'));
breadCrumbs=_.template('<a href="#<%= id %>"><%= content %></a> > ')(current.attributes)+breadCrumbs;
if (current)
breadCrumbs=_.template('<a href="#<%= id %>"><%= content %></a> > ')(current.attributes)+breadCrumbs;
}
if (depth>=100) console.error('Max depth exceeded while making breadCrumbs');
breadCrumbs='<a href="#">Home</a> > '+breadCrumbs;
+11 -21
View File
@@ -5,7 +5,7 @@ define(
'collections/list',
'util/constants',
'text!../../templates/task.html',
'marionette',
'marionette'
],
function (
@@ -53,6 +53,7 @@ define(
'click .note:first': 'addNote',
'click .fold-button:first': 'foldChildren',
'click .fold:first': 'foldChildren',
// TODO make this destroy children too
'click .destroy:first': 'destroy',
// custom events
'focus': 'this.model.focusOnView',
@@ -70,6 +71,7 @@ define(
// backlink
this.model.view = this;
// get only direct children from all tasks in pageView.collection
var children = pageView.collection.filter(
function (child, index, collection) {
return child.get('parentId') === this.model.id;
@@ -98,8 +100,6 @@ define(
'content': data.content,
'isCompleted': data.isCompleted
});
} else {
console.error("task.model.id != data.id", task.model.id, data.id);
}
});
}
@@ -159,8 +159,8 @@ define(
if (this.ui.input.val().length < 2 && this.$('.children>ul').length===0) {
e.preventDefault();
prev = this.focusOnPrev();
this.destroy();
this.model.destroy();
this.destroy();
// set the cursor to the end of the previous input
prev.find('input:first').focus();
var input = prev.find('input:first')[0];
@@ -230,9 +230,8 @@ define(
/** Finish editing an item **/
close: function () {
var value = this.$('.edit:first').val().trim();
this.model.save({
content: value
});
if (this.model.get('content')!=value)
this.model.save({content: value});
this.$el.removeClass('editing');
},
@@ -266,32 +265,23 @@ define(
/** Add a new blank note below this **/
addNote: function () {
var currentId = this.ui.input.data('id') || 0;
// var currentId = this.ui.input.data('id') || 0;
parentId = this.ui.input.data('parent-id');
var index= this.getParentView().collection.indexOf(this.model);
var task = pageView.collection.add({parentId: this.model.get('parentId')});
task.save();
if (index>=0)
this.getParentView().collection.add(task, {at:index+1});
else
this.getParentView().collection.add(task);
console.log(index);
this.ui.input.blur();
task.view.ui.input.focus();
this.$('input:first').blur();
task.focusOnView();
},
/** Fold children of the clicked element */
foldChildren: function () {
if (this.ui.children.length > 0) {
this.ui.children.toggle();
this.$el.find('li:first').toggleClass('folded');
} else {
this.ui.children.show();
this.$el.find('li:first').removeClass('folded');
}
var folded = this.$el.find('li:first').hasClass('folded');
this.model.save({isFolded: !folded});
},
});
+4
View File
@@ -5812,6 +5812,10 @@ body #hackflowy #main .children ul.task-view {
content: "+";
}
.folded.children {
display: none;
}
.task-completed{
text-decoration: line-through;
}
+12 -2
View File
@@ -1,4 +1,8 @@
<li>
<% if (obj.isFolded){ %>
<li class="folded">
<% } else { %>
<li class="">
<% } %>
<div class="task-wrappper">
<div class="task">
<div class="link">
@@ -28,4 +32,10 @@
</div>
</div>
</li>
<div class="children"></div>
<% if (isFolded){ %>
<div class="children folded">
<% } else { %>
<div class="children">
<% } %>
</div>
+22 -7
View File
@@ -42,9 +42,21 @@ app.get('/tasks', function (req, res) {
});
app.post('/tasks', function (req, res) {
console.log({view: "post('/tasks/:id)", id:req.params.id, body:req.body});
Tasks.create({
content: req.body.content,
parentId: parseInt(req.body.parentId) || 0,
parentId: req.body.parentId || '00000000-0000-0000-0000-000000000000',
isCompleted: false
}).then(function (task) {
res.send(task);
});
});
app.put('/tasks', function (req, res) {
console.log({view: "put('/tasks/:id)", id:req.params.id, body:req.body});
Tasks.create({
content: req.body.content,
parentId: req.body.parentId || '00000000-0000-0000-0000-000000000000',
isCompleted: false
}).then(function (task) {
res.send(task);
@@ -52,25 +64,29 @@ app.post('/tasks', function (req, res) {
});
app.get('/tasks/:id', function (req, res) {
console.log({view: "get('/tasks/:id)", id:req.params.id, body:req.body});
Tasks.findById(req.params.id).then(function (task) {
res.send(task);
});
});
app.put('/tasks/:id', function (req, res) {
console.log({isCompleted: req.body.isCompleted});
console.log({view: "put('/tasks/:id)", id:req.params.id, body:req.body});
Tasks.findById(req.params.id).then(function (task) {
task.content = req.body.content;
console.log({view: "put('/tasks/:id)", body:req.body});
task.parentId = parseInt(req.body.parentId) || 0,
task.isCompleted = req.body.isCompleted == 1;
task.priority = req.body.priority;
task.parentId = req.body.parentId || '00000000-0000-0000-0000-000000000000';
task.isFolded = req.body.isFolded == true;
task.isCompleted = req.body.isCompleted == true;
task.save().then(function (task) {
res.send(task);
})
});
});
});
app.delete('/tasks/:id', function (req, res) {
console.log({view: "delete('/tasks/:id)", id:req.params.id, body:req.body});
console.log({isCompleted: req.body.isCompleted});
Tasks.findById(req.params.id).then(function (task) {
task.destroy().then(function () {
res.send('');
@@ -80,7 +96,6 @@ app.delete('/tasks/:id', function (req, res) {
io.sockets.on('connection', function (socket) {
socket.on('task', function (data) {
console.log(data);
socket.broadcast.emit('task', data);
});
});