Skip to content

Commit 95b5d6f

Browse files
authored
Merge pull request #36 from pipedrive/3.0-wip
3.0 release candidate
2 parents 4910ff1 + 06dfd3a commit 95b5d6f

22 files changed

+1139
-949
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ node_modules
33
.idea
44
.DS_Store
55
npm-debug*
6-
test

.travis.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ node_js:
44
- "0.10"
55
- "0.11"
66
- "0.12"
7-
- "4.1"
8-
- "4.2"
7+
- "4"
8+
- "5"
9+
- "6"
10+
- "7"
911

1012
notifications:
1113
email:

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ Merge two objects of the same kind. Returns ```error``` in case of an error to t
8989
* Organizations
9090
* Users
9191

92+
### pipedrive.{Object}.find (params, [fn callback])
93+
Find objects of certain kind by their name/title, using `term` property supplied inside params object. Supported for:
94+
* Deals
95+
* Persons
96+
* Organizations
97+
* Users
98+
9299
# Supported operations for each object
93100

94101
### {object}.get(fieldName)

examples/list-deals.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pipedrive.Filters.getAll({ type: 'deals' }, function(filtersListErr, filtersList
3333
deal.getActivities(function(err, activities) {
3434
if (err) console.log(err);
3535
if(activities === null) activities = [];
36-
console.log('* ' + deal.get('title') + ' (worth ' + deal.get('value') + ' ' + deal.get('currency') + ', has ' + activities.length + ' activit' + (activities.length != 1 ? 'ies' : 'y') + ')');
36+
console.log('* ' + deal.get('title') + ' (worth ' + deal.get('value') + ' ' + deal.get('currency') + ', has ' + activities.length + ' activit' + (activities.length != 1 ? 'ies' : 'y') + ')');
3737
});
3838
});
3939
});

examples/login.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ process.stdin.on('data', function (char) {
2929
Pipedrive.authenticate(setAuthDetails, function(error, authorizations, userData) {
3030
if (error) {
3131
console.log(error);
32+
return;
3233
}
3334

3435
process.stdout.write("\n");

examples/search-users.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
if (!process.argv[2]) {
2+
process.stderr.write('Please provide API token! (e.g. search.js [api_token])' + "\n");
3+
process.exit();
4+
}
5+
if (!process.argv[3]) {
6+
process.stderr.write('Please provide a search term (e.g. search.js [api_token] [term])' + "\n");
7+
process.exit();
8+
}
9+
10+
var Pipedrive = require(__dirname + '/../index');
11+
var pipedrive = new Pipedrive.Client(process.argv[2]);
12+
var _ = require('lodash');
13+
14+
var reqParams = {
15+
term: process.argv[3],
16+
limit: 10
17+
};
18+
19+
pipedrive.Activities.getAll({ user_id: 0 }, function(err, list) {
20+
_.forEach(list, function(item) {
21+
console.log(item.subject);
22+
});
23+
});

examples/search.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
if (!process.argv[2]) {
2+
process.stderr.write('Please provide API token! (e.g. search.js [api_token])' + "\n");
3+
process.exit();
4+
}
5+
if (!process.argv[3]) {
6+
process.stderr.write('Please provide a search term (e.g. search.js [api_token] [term])' + "\n");
7+
process.exit();
8+
}
9+
10+
var Pipedrive = require(__dirname + '/../index');
11+
var pipedrive = new Pipedrive.Client(process.argv[2]);
12+
var _ = require('lodash');
13+
14+
var reqParams = {
15+
term: process.argv[3],
16+
limit: 10
17+
};
18+
19+
pipedrive.SearchResults.getAll(reqParams, function(searchErr, searchResults) {
20+
console.log(arguments);
21+
process.exit(0);
22+
if (searchErr) console.log(searchErr);
23+
console.log('Found ' + searchResults.length + ' results:');
24+
_.each(searchResults, function(result) {
25+
console.log(result.type + ' ' + result.title + ' (id: ' + result.id + ')');
26+
});
27+
});

lib/Collection.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
(function() {
2+
'use strict';
3+
4+
var _ = require('lodash'),
5+
CollectionItem = require(__dirname + '/CollectionItem'),
6+
RestHandlers = require(__dirname + '/restHandlers'),
7+
blueprint = require(__dirname + '/blueprint'),
8+
inflection = require(__dirname + '/inflection');
9+
10+
module.exports = Collection;
11+
12+
function Collection(kind, options) {
13+
14+
var wrapCollectionItems = require(__dirname + '/wrapCollectionItems'),
15+
restHandlers = new RestHandlers(options);
16+
17+
this.getAll = function(params, getAllCallback) {
18+
return restHandlers.listItems(kind, params, function(error, data, additionalData, req, res) {
19+
var collectionItems = wrapCollectionItems(data, kind, options);
20+
(_.isFunction(params) ? params : getAllCallback)(error, collectionItems, additionalData, req, res);
21+
});
22+
};
23+
24+
this.get = function(id, getCallback, params) {
25+
if (!id) {
26+
throw new Error('Cannot get ' + inflection.singularize(kind) + ' - ID must be given.');
27+
}
28+
29+
return restHandlers.getItem(kind, id, function(error, data, additionalData, req, res) {
30+
if (data !== null && !_.isUndefined(data) && data.id) {
31+
getCallback(null, new CollectionItem(kind, data, data.id, options), additionalData, req, res);
32+
}
33+
else {
34+
getCallback(error, data, additionalData, req, res);
35+
}
36+
}, params);
37+
38+
};
39+
40+
this.add = function(params, callback) {
41+
return restHandlers.addItem(kind, params, callback);
42+
};
43+
44+
this.remove = function(id, params, callback) {
45+
return restHandlers.removeItem(id, kind, params, callback);
46+
};
47+
48+
this.removeMany = function(ids, params, callback) {
49+
return restHandlers.removeManyItems(ids, kind, params, callback);
50+
};
51+
52+
this.update = function(id, params, callback) {
53+
return restHandlers.editItem(id, kind, params, callback);
54+
};
55+
56+
if (_.indexOf(blueprint.mergeableObjects, kind) !== -1) {
57+
this.merge = function(whichId, withId, callback) {
58+
if (!whichId || !withId) {
59+
callback(new Error('The parameters whichId and withId must be provided.'));
60+
return false;
61+
}
62+
return restHandlers.mergeItem(whichId, withId, kind, callback);
63+
};
64+
}
65+
66+
if (_.indexOf(blueprint.searchableObjects, kind) !== -1) {
67+
this.find = function(params, callback) {
68+
if (!params.term) {
69+
callback(new Error('The term parameter must be supplied for finding ' + kind + '.'));
70+
return false;
71+
}
72+
return restHandlers.findItems(kind, params, function(error, data, additionalData, req, res) {
73+
var collectionItems = wrapCollectionItems(data, kind, options);
74+
callback(error, collectionItems, additionalData, req, res);
75+
});
76+
};
77+
}
78+
79+
if (_.indexOf(blueprint.timelineableObjects, kind) !== -1) {
80+
this.getTimeline = function(params, callback) {
81+
return restHandlers.timelineItems(kind, params, function(error, data, additionalData, req, res) {
82+
(_.isFunction(params) ? params : callback)(error, data, additionalData, req, res);
83+
});
84+
};
85+
}
86+
87+
if (_.indexOf(blueprint.objectsSupportingFieldValueSearch, kind) !== -1) {
88+
this.field = function(params, callback) {
89+
if (!params.field_type || !params.field_key || !params.term) {
90+
callback(new Error('The field_type, field_key and term parameters must be supplied for field-value search.'));
91+
return false;
92+
}
93+
if (blueprint.supportedFieldTypes.indexOf(params.field_type) < 0) {
94+
callback(new Error('The field_type given for field-value search was invalid. Must be one of the following: ' + blueprint.supportedFieldTypes.join(', ')));
95+
return false;
96+
}
97+
params.exact_match = params.exact_match ? '1' : '0';
98+
return restHandlers.searchFields(kind, params, function(error, data, additionalData, req, res) {
99+
var collectionItems = wrapCollectionItems(data, inflection.pluralize(params.field_type.replace('Field','').toLowerCase()), options);
100+
callback(error, collectionItems, additionalData, req, res);
101+
});
102+
};
103+
}
104+
105+
return this;
106+
}
107+
})();

lib/CollectionItem.js

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
(function() {
2+
'use strict';
3+
4+
var _ = require('lodash'),
5+
RestHandlers = require(__dirname + '/restHandlers'),
6+
blueprint = require(__dirname + '/blueprint'),
7+
inflection = require(__dirname + '/inflection');
8+
9+
function CollectionItem(kind, data, itemId, options, undefinedProperty) {
10+
11+
var wrapCollectionItems = require(__dirname + '/wrapCollectionItems'),
12+
restHandlers = new RestHandlers(options);
13+
14+
this.id = itemId;
15+
16+
var currentItem = this;
17+
18+
_.each(data, function(value, key) {
19+
currentItem[key] = value;
20+
});
21+
22+
var changedData = {};
23+
24+
this.save = function(saveCallback) {
25+
restHandlers.editItem(data.id, kind, changedData, saveCallback);
26+
changedData = {};
27+
return currentItem;
28+
};
29+
30+
this.remove = function(successCallback) {
31+
return restHandlers.removeItem(data.id, kind, {}, successCallback);
32+
};
33+
34+
this.get = function(key) {
35+
return (!_.isUndefined(data[key]) ? data[key] : undefinedProperty);
36+
};
37+
38+
this.merge = function(withId, callback) {
39+
return restHandlers.mergeItem(data.id, withId, kind, callback);
40+
};
41+
42+
this.duplicate = function(callback) {
43+
return restHandlers.duplicateItem(data.id, kind, callback);
44+
};
45+
46+
this.toObject = function() {
47+
var obj = {};
48+
_.each(_.keys(this), (function(key) {
49+
if (typeof this[key] !== 'function') {
50+
obj[key] = _.clone(this[key]);
51+
}
52+
}).bind(this));
53+
return obj;
54+
};
55+
56+
this.set = function(key, value) {
57+
if (key === 'id') {
58+
throw new Error(inflection.capitalize(kind) + ' ID cannot be changed.');
59+
}
60+
var changeValue = function(keyToChange, valueToChange) {
61+
var isObject = (typeof data[keyToChange] == 'object' && data[keyToChange]),
62+
isSameType = (typeof data[keyToChange] === typeof valueToChange),
63+
isUndefinedOrNull = (_.isNull(data[keyToChange]) || typeof data[keyToChange] == 'undefined');
64+
65+
if (isObject || isSameType || (!isSameType && isUndefinedOrNull)) {
66+
data[keyToChange] = valueToChange;
67+
currentItem[keyToChange] = valueToChange;
68+
changedData[keyToChange] = valueToChange;
69+
}
70+
else {
71+
throw new Error('Can not change ' + keyToChange + ' - ' + typeof data[keyToChange] + ' must be given.');
72+
}
73+
};
74+
75+
if (typeof key === 'object' && typeof value === 'undefined') {
76+
_.each(key, function(cValue, cKey) {
77+
changeValue(cKey, cValue);
78+
});
79+
}
80+
else {
81+
changeValue(key, value);
82+
}
83+
84+
return currentItem;
85+
};
86+
87+
// generator of sub-items management (like deal getProducts, addProduct, updateProduct, deleteProduct):
88+
var generateSubMethod = function(methodType, kind, relatedObject) {
89+
var methodSuffix = relatedObject.substr(0,1).toUpperCase() + relatedObject.substr(1);
90+
91+
if (methodType !== 'get') {
92+
methodSuffix = inflection.singularize(methodSuffix);
93+
}
94+
95+
var objectKey = kind + '/' + currentItem.id + '/' + relatedObject;
96+
97+
currentItem[methodType + methodSuffix] = function(params, callback) {
98+
99+
callback = (_.isFunction(params) && _.isUndefined(callback) ? params : callback);
100+
params = (_.isFunction(params) && _.isUndefined(callback) ? {} : params);
101+
if (!_.isFunction(callback)) {
102+
callback = function() {};
103+
}
104+
105+
var relatedObjectPath = relatedObject;
106+
107+
if (blueprint.selfManagedRelatedObjects.indexOf(relatedObject) !== -1) {
108+
relatedObjectPath = objectKey;
109+
}
110+
111+
switch (methodType) {
112+
case 'get':
113+
return restHandlers.listItems(objectKey, params, function(error, data, additionalData, req, res){
114+
var collectionItems = wrapCollectionItems(data, relatedObjectPath, options);
115+
callback(error, collectionItems, additionalData, req, res);
116+
});
117+
case 'add':
118+
return restHandlers.addItem(objectKey, params, function(error, data, additionalData, req, res){
119+
var collectionItems = wrapCollectionItems(data, relatedObjectPath, options);
120+
callback(error, collectionItems, additionalData, req, res);
121+
});
122+
case 'update':
123+
return restHandlers.editItem(params.id, objectKey, params, function(error, data, additionalData, req, res){
124+
var collectionItems = wrapCollectionItems(data, relatedObjectPath, options);
125+
callback(error, collectionItems, additionalData, req, res);
126+
});
127+
case 'delete':
128+
return restHandlers.removeItem(false, objectKey, params, function(error, data, additionalData, req, res){
129+
var collectionItems = wrapCollectionItems(data, relatedObjectPath, options);
130+
callback(error, collectionItems, additionalData, req, res);
131+
});
132+
default:
133+
break;
134+
}
135+
};
136+
};
137+
138+
// attaches get-methods for sub-objects (like deal products, organization persons, etc):
139+
if (_.isObject(blueprint.apiRelatedObjects[kind])) {
140+
_.each(blueprint.apiRelatedObjects[kind], function(relatedObject) {
141+
generateSubMethod('get', kind, relatedObject);
142+
});
143+
}
144+
145+
// attaches editing capabilities for sub-objects that should have them:
146+
if (_.isArray(blueprint.editableSubItems[kind])) {
147+
_.each(blueprint.editableSubItems[kind], function(relatedObject) {
148+
149+
generateSubMethod('add', kind, relatedObject);
150+
generateSubMethod('update', kind, relatedObject);
151+
generateSubMethod('delete', kind, relatedObject);
152+
153+
});
154+
}
155+
156+
return currentItem;
157+
}
158+
159+
module.exports = CollectionItem;
160+
161+
})();

0 commit comments

Comments
 (0)