Skip to content

Commit

Permalink
Images, improvements, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
ialexi committed Dec 17, 2009
1 parent 6ca31a7 commit 1e721f0
Show file tree
Hide file tree
Showing 22 changed files with 3,813 additions and 39 deletions.
87 changes: 84 additions & 3 deletions apps/contacts/controllers/contacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
*/
Contacts.contactsController = SC.ArrayController.create(SC.CollectionViewDelegate,
/** @scope Contacts.contactsController.prototype */ {
inputBinding: "Contacts.groupsController.selection",
inputBindingDefault: SC.Binding.single(),
contentBinding: ".*input.contacts",
contentBinding: "Contacts.groupsController.effectiveSelection",
canAddContent: YES,
canReorderContent: NO,
canRemoveContent: YES,
isEditable: YES,
orderBy: "lastName",

// deleting contacts is handled by contactsController.
// removing contacts from groups is handled by the groupConttroller.
inAll: YES, // can be NO or YES. If YES, the parent controller is called to remove items.
inAllBinding: "Contacts.groupsController.allIsSelected",

collectionViewDragDataTypes: function(view) {
return [Contacts.Contact];
Expand All @@ -36,5 +40,82 @@ Contacts.contactsController = SC.ArrayController.create(SC.CollectionViewDelegat

collectionViewComputeDragOperations: function(view, drag) {
return SC.DRAG_COPY;
},

collectionViewDeleteContent: function(view, content, indexes) {
// get records first for safety :)
var records = indexes.map(function(idx) {
return this.objectAt(idx);
}, this);

// we only handle deletion if in "All" category.
if (!this.get("inAll")) {
Contacts.groupsController.removeContacts(records);
return;
}

// process OUR WAY!
this._pendingOperation = { action: "deleteContacts", records: records, indexes: indexes };

// calculate text
var text = "";
var name = "Contact";
var len = indexes.get("length");
if (len > 1) {
name += "s";
text = "Are you sure you want to delete these " + len + " contacts?";
} else {
text = "Are you sure you want to delete this contact?";
}

// show warning
SC.AlertPane.warn(
"Be Careful!",
text,
null,
"Keep " + name,
"Delete " + name,
null,
this
);
},

deleteContacts: function(op)
{
var records = op.records, indexes = op.indexes;
records.invoke('destroy');

var selIndex = indexes.get('min') - 1;
if (selIndex < 0) selIndex = 0;
this.selectObject(this.objectAt(selIndex));

Contacts.store.commitRecords();
},

alertPaneDidDismiss: function(pane, status) {
if (!this._pendingOperation) return;
switch (status) {
case SC.BUTTON2_STATUS:
this[this._pendingOperation.action].call(this, this._pendingOperation);
this._pendingOperation = null;
break;
case SC.BUTTON1_STATUS:
break;
}
},

addContact: function() {
var contact;
contact = Contacts.store.createRecord(Contacts.Contact, { firstName: "", lastName: "" }); // no name.

// add contact to current group if needed
if (!this.get("inAll")) Contacts.groupsController.addNewContact(contact);

this.selectObject(contact);
this.invokeLater(function(){
Contacts.contactController.beginEditing();
});

contact.commitRecord();
}
}) ;
122 changes: 120 additions & 2 deletions apps/contacts/controllers/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,56 @@
@extends SC.ArrayController
*/
Contacts.groupsController = SC.ArrayController.create(
Contacts.groupsController = SC.ArrayController.create(SC.CollectionViewDelegate,
/** @scope Contacts.groupsController.prototype */ {
allowMultipleSelection: NO,
allowMultipleSelection: YES,
all: null,
selection: null,
_observingGroups: [],
allDidChange: function(){
if (!this.get("selection")) {
this.set("effectiveSelection", this.get("all"));
this.set("allIsSelected", YES);
} else {
this.recalculateFromGroups();
}
}.observes("all"),

selectAllGroup: function(){
this.set("selection", null);
this.set("effectiveSelection", this.get("all"));
this.set("allIsSelected", YES);
},

selectionDidChange: function() {
for (var i = 0; i < this._observingGroups.length; i++){
this._observingGroups[i].removeObserver("contacts", this, this.groupDidChange);
}
this._observingGroups.length = 0;
if (this.get("selection")) {
this.get("selection").forEach(function(item) {
item.addObserver("contacts", this, this.groupDidChange);
this._observingGroups.push(item);
}, this);
}
this.recalculateFromGroups();
}.observes("selection"),

groupDidChange: function() {
this.recalculateFromGroups();
},

recalculateFromGroups: function() {
if (this.get("selection") && this.get("selection").get("length") > 0) {
var result = SC.Set.create();
this.get("selection").forEach(function(group){
result.addEach(group.get("contacts"));
});

this.set("effectiveSelection", result);
this.set("allIsSelected", NO);
}
},

computeDragOperations: function(group, drag){
var data = drag.dataForType(Contacts.Contact);
Expand All @@ -25,5 +72,76 @@ Contacts.groupsController = SC.ArrayController.create(
var data = drag.dataForType(Contacts.Contact);
group.get("contacts").pushObjects(data);
Contacts.store.commitRecords();
},

collectionViewDeleteContent: function(view, content, indexes) {
this._pendingOperation = { action: "deleteGroups", indexes: indexes };
SC.AlertPane.warn(
"Be Careful!",
"Are you sure you want to delete these " + indexes.get("length") + " groups?",
null,
"Keep Groups",
"Delete Groups",
null,
this
);
},

deleteGroups: function(op)
{
var indexes = op.indexes;
var records = indexes.map(function(idx) {
return this.objectAt(idx);
}, this);
records.invoke('destroy');

var selIndex = indexes.get('min') - 1;
if (selIndex < 0) selIndex = 0;
this.selectObject(this.objectAt(selIndex));

Contacts.store.commitRecords();
},

alertPaneDidDismiss: function(pane, status) {
if (!this._pendingOperation) return;
switch (status) {
case SC.BUTTON2_STATUS:
this[this._pendingOperation.action].call(this, this._pendingOperation);
this._pendingOperation = null;
break;
case SC.BUTTON1_STATUS:
break;
}
},

addGroup: function() {
var group;
group = Contacts.store.createRecord(Contacts.Group, { "name": "New Group" });
this.selectObject(group);
this.invokeLater(function(){
var contentIndex = this.indexOf(group);
var list = Contacts.mainPage.getPath("mainPane.splitter.topLeftView.groupList.contentView");
var listItem = list.itemViewForContentIndex(contentIndex);
listItem.beginEditing();
});
},

removeContacts: function(contacts) {
var sel = this.get("selection");
if (!sel) return;

sel.forEach(function(item) {
item.get("contacts").removeObjects(contacts);
});
},

addNewContact: function(contact) {
var sel = this.get("selection");
if (!sel) return;
var pg = [];
sel.forEach(function(item) {
pg.push(item);
});
contact.set("pendingGroups", pg);
}
}) ;
2 changes: 1 addition & 1 deletion apps/contacts/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Contacts = SC.Application.create(
// connect to a backend server. The default setup below connects the store
// to any fixtures you define.
store: SC.Store.create({
}).from(SC.Record.fixtures) //('Contacts.Provider')
}).from('Contacts.Provider')

// TODO: Add global constants or singleton objects needed by your app here.

Expand Down
48 changes: 43 additions & 5 deletions apps/contacts/data_sources/provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,38 @@ Contacts.Provider = SC.DataSource.extend(
if (SC.kindOf(store.recordTypeFor(storeKey), Contacts.Group)) {
var url = "/server/group/" + store.idFor(storeKey);
SC.Request.getUrl(url).json().notify(this, "didRetrieveGroup", store, storeKey).send();
return YES;
}
return NO;
},

createRecord: function(store, storeKey) {
// TODO: Add handlers to submit new records to the data source.
// call store.dataSourceDidComplete(storeKey) when done.
var url = "";

if (SC.kindOf(store.recordTypeFor(storeKey), Contacts.Group)) {
url = "/server/groups";
} else if (SC.kindOf(store.recordTypeFor(storeKey), Contacts.Contact)) {
url = "/server/contacts";
}

if (url !== "") {
SC.Request.postUrl(url).json().notify(this, "didCreateRecord", store, storeKey)
.send(store.readDataHash(storeKey));
return YES;
}

return NO ; // return YES if you handled the storeKey
},

didCreateRecord: function(response, store, storeKey) {
if (SC.ok(response)) {
var hash = response.get("body");
if (hash) hash = hash[0];
store.dataSourceDidComplete(storeKey, hash, hash.guid);
return YES;
}
return NO;
},

updateRecord: function(store, storeKey) {
var url = "";
Expand Down Expand Up @@ -125,11 +148,26 @@ Contacts.Provider = SC.DataSource.extend(
},

destroyRecord: function(store, storeKey) {

// TODO: Add handlers to destroy records on the data source.
// call store.dataSourceDidDestroy(storeKey) when done
var url = "";
if (SC.kindOf(store.recordTypeFor(storeKey), Contacts.Group)) {
url = "/server/group/";
} else if (SC.kindOf(store.recordTypeFor(storeKey), Contacts.Contact)) {
url = "/server/contact/";
}

if (url !== "") {
url += store.idFor(storeKey);
SC.Request.deleteUrl(url).json().notify(this, "didDestroyRecord", store, storeKey)
.send(store.readDataHash(storeKey));
}

return NO ; // return YES if you handled the storeKey
},

didDestroyRecord: function(response, store, storeKey) {
if (SC.ok(response)) {
store.dataSourceDidDestroy(storeKey);
} else store.dataSourceDidError(storeKey);
}

}) ;
21 changes: 17 additions & 4 deletions apps/contacts/models/contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ Contacts.Contact = SC.Record.extend(
// full name
fullName: function()
{
var val = this.get("firstName") + " " + this.get("lastName");
val = val.trim();
if (val === "") val = this.get("company");
var val = (this.get("firstName") || "") + " " + (this.get("lastName") || "");

if (val.trim() === "") val = this.get("company") || "";

return val;
}.property('firstName', 'lastName', 'company').cacheable(),

Expand All @@ -39,5 +39,18 @@ Contacts.Contact = SC.Record.extend(

groups: SC.Record.toMany("Contacts.Group", {
inverse: "contacts", isMaster: NO
})
}),

pendingGroups: [],
storeDidChangeProperties: function() {
if (this.get("guid")) {
if (this.get("pendingGroups") && this.get("pendingGroups").get("length") > 0) {
this.get("pendingGroups").forEach(function(item){
item.get("contacts").pushObject(this);
}, this);
this.set("pendingGroups", []);
Contacts.store.commitRecords();
}
}
}
}) ;
Empty file.
3 changes: 3 additions & 0 deletions apps/contacts/resources/images/icons/images.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.icons .plus-active.icon, .icons.plus-active.icon { background:static_url('images/icons/sprites.png') no-repeat; background-position:-0px -0px; }
.icons .plus.icon, .icons.plus.icon { background:static_url('images/icons/sprites.png') no-repeat; background-position:-32px -0px; }
.icons .search-16.icon, .icons.search-16.icon { background:static_url('images/icons/sprites.png') no-repeat; background-position:-64px -0px; }
Binary file added apps/contacts/resources/images/icons/sprites.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 1e721f0

Please sign in to comment.