The caseblocks
NPM package is a library to interact with the CaseBlocks REST API.
It assumes that it will be executed in a Node.js envirnoment.
As with any NPM package:
npm install caseblocks --save
The Caseblocks
object, which is the main proxy with the Caseblocks REST API, has to first be initialized with the proper parameters:
const Caseblocks = require('caseblocks')
Caseblocks.setup("http://yourpathtocaseblocks.com:8080", "your_user_token")
The user token may be found in the User settings section of the Caseblocks web interface.
-
arguments:
{object} attributes
The attributes of the case type to create
-
returns:
{Casetype}
The instance ofCasetype
​
- arguments:
{string} caseTypeId
theid
(primary key) attribute of a case type.
- returns:
{Promise.<Case>}
Gets the case type from the server and returns the casetype object.
Caseblocks.Casetype.get("15").then(function(casetype) {
console.log(casetype.id)
}).catch(function(err){
console.error(err);
});
Returns all the field objects in the casetype of the specified type, for example 'documents'.
Caseblocks.Casetype.get("15").then(function(casetype) {
documentFields = casetype.fieldsOfType('document')
console.log(documentFields)
}).catch(function(err){
console.error(err);
});
- arguments:
{string} caseTypeCode
The plural underscored name of the case type this case will belong to.{number|string} caseTypeId
The id of the case type this case will belong to.{object} caseData
The attributes this case will have.
- returns:
{Promise.<Case>}
Creates a case document in the supplied case type (case_type_code
and case_type_id
) with the data supplied.
Caseblocks.Case.create("support_requests", 42, {title: 'test1'})
.then(function(doc) {
console.log(doc.attributes.title)
}).catch(function(err){
console.error(err)
});
- arguments:
{string} caseTypeCode
The plural underscored name of the case type this case belongs to.{string} caseId
The primary key for the case. As of today it is an instance ofmongodb.ObjectId
from the MongoDB NPM package.
- returns
{Promise.<Case>}
Retrieves a case from caseblocks supplying the case type code and the id of the document.
Caseblocks.Case.get("support_requests", "550c40d1841976debf000003")
.then(function(doc) {
doc.attributes._id.should.equal("550c40d1841976debf000003")
console.log(doc.id);
console.log(doc.attributes.title)
}).catch(function(err){
console.error(err)
});
This function provides the ability to search for documents and return an array of matching cases. As of version 1.2.0 it has two different usages depending on the nature of the arguments passed:
WARNING: This way of usign it is deprecated and will eventually be removed.
- arguments:
{string|number} caseTypeRepresentation
The id of the case type that we want to search instances of.{string} searchQuery
A search query following the Elasticsearch string query mini language syntax.
- returns
{Promise.<[Case]>}
An array ofCase
instances which are the same as you get from theget
method. The length of the resulting[Case]
array is limited to 10 elements.
Caseblocks.Case.search(31416, 'full_name:"Rick Sanchez" AND dimension:"C-137"')
.then(results => {
console.log("Found " + results.length + " cases!")
resulsts.map(caseInstance => {
console.log(caseInstance.attributes.title)
})
})
.catch(err => {
console.error(err.message)
})
A new, more convenient way of searching cases uses the following signarture:
- arguments:
{string} caseTypeRepresentation
The singular underscored name of the case type we want to search instances of.{string} searchQuery
A search query following the Elasticsearch string query mini language syntax.
- returns
{Promise.<[Case]>}
An array ofCase
instances which are the same as you get from theget
method. There is no limit on the number of cases retrieved.
Caseblocks.Case.search('mad_scientists', 'full_name:"Rick Sanchez" AND dimension:"C-137"')
.then(results => {
console.log("Found " + results.length + " cases!")
resulsts.map(caseInstance => {
console.log(caseInstance.attributes.title)
})
})
.catch(err => {
console.error(err.message)
})
Saves any changes made to the current case object.
Caseblocks.Case.get("support_requests", "550c40d1841976debf000003")
.then(function(doc) {
var d = new Date();
var n = d.toUTCString();
doc.attributes.systems_involved = n
doc.save().then(function(doc) {
console.log("Saved!");
}).catch(function(err){
console.error(err);
});
});
Not implemented yet
Retrieves related cases from caseblocks supplying the case type code and the id of the document.
Caseblocks.Case.get("support_requests", "550c40d1841976debf000003")
.then(function(doc) {
doc.related(related_case_type_code, relation_id)
.then(function(related_docs) {
console.log(related_docs[0].id)
console.log(related_docs[0].attributes.title)
})
}).catch(function(err){
console.log(err)
});
-
arguments:
{string} relatedCaseTypeCode
The singular underscored name of the case type we want to search instances of.
-
returns:
{Promise.<[object]>}
A promise that resolves into an array of objects, one for each different relationship for which there are cases of the type that corresponds torelatedCaseTypeCode
. It has the following internal structure:[ { relationship_0: { id: 530, from_fieldset_key: 'field_set_name_0', to_fieldset_key: 'field_set_name_1', position: 1, to_organization_type_id: 161, from_work_type_id: 162, // ... from_key: 'field_name_0', to_key: 'field_name_1' }, cases: [ case_00, // ... case_0n ] }, // ... { relationship_m: { id: 530, from_fieldset_key: 'field_set_name_0', to_fieldset_key: 'field_set_name_1', position: 1, to_organization_type_id: 161, from_work_type_id: 162, // ... from_key: 'field_name_0', to_key: 'field_name_1' }, cases: [ case_m0, // ... case_mn ] }, ]
​
Retrieves the cases that belong to this one and are of the case type that corresponds to the value of relatedCaseTypeCode
. For example:
Caseblocks.Case.get('584fd9201e7d66d2870d80ba')
.then(result => {
result.related('grandchild')
.then(relationships => {
console.log(relationships[0].cases[0].attributes.full_name)
})
})
.catch(err => {
console.log(err.message)
});
Retrieves the teams that are participants in this case
Caseblocks.Case.get("support_requests", "550c40d1841976debf000003")
.then(function(doc) {
doc.teams().then(function(teams) {
console.log(teams[0].display_name)
})
}).catch(function(err){
console.log(err)
});
Retrieves the users that are listed as an individual user as a participant on this case
Caseblocks.Case.get("support_requests", "550c40d1841976debf000003")
.then(function(doc) {
doc.users().then(function(users) {
console.log(users[0].display_name)
})
}).catch(function(err){
console.log(err)
});
Retrieves all the users that are participants including team members.
Caseblocks.Case.get("support_requests", "550c40d1841976debf000003")
.then(function(doc) {
doc.participants().then(function(users) {
console.log(users[0].display_name)
})
}).catch(function(err){
console.log(err)
});
The constructor for document takes the attributes of the document and the case object it is contained within.
- arguments:
{string|number} caseTypeId
The id of the case type this case belongs to{object} caseInstance
The case to attach it to{string} fileName
The name of the file{string} contents
The content of the file
- returns:
{Promise.<Document>}
A promise that resolves to the metadata about the saved file.
This function creates a document from a string and attaches it to caseInstance
.
const caseTypeId = 1964
fileName = 'secret_message.txt'
fileContents = 'The bird is in the nest.'
Caseblocks.Case.get('secret_agents', '09eef94cbc39370046000da1')
.then(caseInstance =>
Caseblocks.Document.fromString(
caseTypeId,
caseInstance,
fileName,
fileContents
).then(document => {
// Do something with the document
}).catch(err => {
// Handle error
})
).catch(err => {
// Handle error
})
Once an invocation of this method has succeeded a new text file may be found in the documents section of the view of the specified case. Its name and contents
will be fileName
and contents
.
Renames the document in the case and updates any related document fields
Caseblocks.Case.get("support_requests", "case-with-documents")
.then(function(caseInstance) {
docs = caseInstance.documents()
if (docs.length > 0) {
docs[0].rename("new-filename.pdf").then(function(doc) {
console.log(doc.file_name)
}).catch(function(err){
console.log(err)
});
}
}).catch(function(err){
console.error(err)
});
- returns:
{Promise.<boolean>}
A promise that resolves intoTrue
if and only if the document instance has been successfully deleted. - throws:
{Error}
When the deletion was not successful.
Deletes both de document instance and the file in the server it represents.
// Assuming Field Agent case with id '09eef94cbc3k70046000da1'
// has one or more documents.
Caseblocks.Case.get('field_agent', '09eef94cbc3k70046000da1')
.then(fieldAgent =>
fieldAgent.documents().pop()
)
.then(document =>
document.delete()
.then(deleted => {
if (deleted) {
const msg = `The document "${classifiedFile}" has been deleted.`
console.log(msg)
}
})
)
.catch(err => {
// Handle error
})
- arguments:
{Case} caseInstance
the case to which attach a copy of the file that the document instance represents.{object} options
a plain object whose attributes modify the operations of this function:{string} targetFilename
The name the file copied should have in the destination case folder. Its default value is the name of the source file (this.file_name
). It should include the file name extension.{boolean} overwriteOnFound
true
if the file contents of a destination file with the same name are to be overwritten by the ones of the document being copied. Its default value isfalse
.
- returns:
{Promise.<Document>}
A promise that resolves into the instance of the new instance ofDocument
attached tocaseInstance
, whose file contents are a copy of the ones found inthis
. The promise is rejected if an error occurred at any of the stages of the operation it implements or ifcaseInstance.documents().some(d => d.file_name === options.targetFilename)
andoptions.overwriteOnFound === false
.
Copies the Document
instance that this method is called upon and attaches it to the target Case
instance, copying as well the contents of the file this it represents.
Caseblocks.Case.get('capulet_members', '82aef94cbc3d70046000da1')
.then(juliet =>
Caseblocks.Case.get('montague_members', '09eef94cbc3k70046000da1')
.then(romeo => {
const document = juliet.documents().find(
document => document.file_name ==== 'desperate_love_letter.md'
)
return document.copyToCase(romeo, {
newFileName: 'letter_from_juliet.md'
})
})
)
.then(newDocument => {
// At this point newDocument belongs to romeo and represents a file attached
// to this case with name 'letter_from_juliet.md' and the same contents
// as the original 'desperate_love_letter.md' file that is still attached
// to the juliet case.
})
.catch(err => {
// Handle error
})
Retrieve a tasklist matching the id supplied.
Caseblocks.Tasklist.get("550c40d1841976debf00000a").then(function(tasklist) {
console.log(tasklist.name)
}).catch(function(err){
console.error(err)
})
Retrieves multiple tasklists in one go. Pass in an array of string id's and the matching Tasklists will be returned in an array.
const ids = [
"550c40d1841976debf00000a",
"550c40d1841976debf00000c",
"550c40d1841976debf00000e"
];
Caseblocks.Tasklist.getAll(ids).then(function(tasklists) {
console.log(tasklists.length)
}).catch(function(err){
console.error(err)
});
Retrieves all tasks associated with this tasklist, returns a promise with an array of tasks.
const ids = [
"550c40d9841976debf000018",
"550c40d9841976debf00001a",
"550c40d9841976debf00001c"
];
Caseblocks.Tasklist.getAll(ids).then(function(tasklists) {
var tasklists_returned = tasklists.length
tasklists.forEach(function(tasklist) {
tasklist.tasks().then(function(tasks) {
tasks.forEach(function(task) {
all_tasks.push(task)
});
tasklists_count++;
if (tasklists_returned == tasklists_count) {
done();
}
}).catch(function(err){
done(err);
});
})
}).catch(function(err){
done(err);
});
Retrieves a task matching the id supplied
Caseblocks.Task.get("550c40d1841976debf000004").then(function(task) {
task.description.should.equal("Create Pull Request")
done();
}).catch(function(err){
done(err);
})
Retrieves multiple tasks in one go. Pass in an array of string id's and the matching Tasks will be returned in an array.
const ids = [
"550c40d1841976debf000004",
"550c40d1841976debf000005",
"550c40d1841976debf000006",
"550c40d1841976debf000007",
"550c40d1841976debf000008",
"550c40d1841976debf000009"
]
Caseblocks.Task.getAll(ids).then(function(tasks) {
tasks.length.should.equal(6)
tasks[2].description.should.equal("Merge in Github")
done();
}).catch(function(err){
done(err);
});
Retrieves a team matching the id supplied
Caseblocks.Team.get(5).then(function(team) {
console.log(team.display_name))
}).catch(function(err){
console.err(err)
})
Retrieves the users that are members in this team.
Caseblocks.Team.get(5).then(function(team) {
team.members().then(function(users) {
users.map(function(user) {
console.log(user.display_name)
})
})
}).catch(function(err){
console.err(err)
})
Retrieves a user matching the id supplied
Caseblocks.User.get(5).then(function(user) {
console.log(user.display_name))
}).catch(function(err){
console.err(err)
})
Retrieves the complete list of users for an account
Caseblocks.User.getAll().then(function(users) {
for (var i=0; i <= users.length; i++) {
console.log(users[i].display_name))
}
}).catch(function(err){
console.err(err)
})
Retrieves a bucket from caseblocks supplying the id of the bucket and its case type code.
Caseblocks.Bucket.get(6, "bulk_uplifts").then(function(bucket) {
log(bucket.attributes.name)
}).catch(function(err) {
log("Failed to get bucket")
fail(JSON.stringify(err))
})
Saves any changes made to the current document.
Caseblocks.Bucket.get(6, "bulk_uplifts").then(function(bucket) {
log(bucket.attributes.name)
bucket.stats().then(function(bucket_stats) {
summary = bucket_stats["bucket_summary"]
log("")
log("Summary")
log("=======")
log("Total: " + summary.total)
log("Last 24 hrs: " + summary.total_in_last_24_hours)
log("")
log("Stats")
log("=====")
stats = bucket_stats["bucket_stats"]
for(i in stats) {
log(" " + stats[i].term + ": " + stats[i].count)
}
}).catch(function(err) {
log("Failed to get stats")
fail(JSON.stringify(err))
})
}).catch(function(err) {
log("Failed to get bucket")
fail(JSON.stringify(err))
})
Retrieves cases contained in the bucket by page. Parameters are optional and page
defaults to 0 and pageSize
defaults to 10.
Caseblocks.Bucket.get(6, "bulk_uplifts").then(function(bucket) {
log(bucket.attributes.name)
bucket.cases(0,10).then(function(cases) {
log("Found " + cases.length + " cases.")
for(kase of cases) {
log(kase.attributes.title)
}
exit(payload)
}).catch(function(err) {
log("Failed to get cases")
fail(JSON.stringify(err))
})
}).catch(function(err) {
log("Failed to get bucket")
fail(JSON.stringify(err))
})
The email functions allow you to send an email either through mandrill or smtp. You can also use the mandrill templating features.
Instantiate a new Caseblocks.Email object passing in your initial configuration, like keys and server details, then you can add recipients and setup your from address, subject, and body (html or text).
Mandrill is set as default and requires 'key' to be passed in when instantiating the object.
Other properties available are
- serverType - 'mandrillapp' or 'smtp' values are valid.
- smtpServer - required if serverType is smtp and is host of smtp server to use
- key - required if serverType is mandrill and is they access token key for your account
Example:
let email = new Caseblocks.Email({"key": "sample-key"})
email.to("[email protected]")
email.to("[email protected]")
email.bcc("[email protected]")
email.from("[email protected]")
email.subject("This is a sample Subject")
email.body("<html><body style='text-align: center;'><h1>Hello World</h1></body></html>")
email.send().then(function(result) {
exit(result);
})
The above example sets up the key for mandrill then adds a to address, bcc address, sets up the from address, subject and then adds an html body, then sends the email.
Note: Sending through SMTP is not implemented yet.
You can call to many times to add recipients to the email. Name is an optional parameter.
You can call cc many times to add recipients to the email. Name is an optional parameter.
You can call bcc many times to add recipients to the email. Name is an optional parameter.
The from function, sets the from address of the email. Again, name is optional.
Sets the subject for the email, text should be a string that will be used as the subject in the email.
Sets the html body of the email, which will also automatically set the text using an html-to-text conversion tool.
Alias of body
Sets the text only version of the email. This should be set after html as setting html overwrites this value.
This function sends an email using either mandrill or smtp (to be implemented). The above example shows how to setup an email before you call send.
Sends an email using a mandrill template. The first parameter is a string that should match an existing mandrill template you wish to use. The second parameter is a hash of data to be used with the template, eg
{
"title": "Have a merry Christmas",
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
}
This data will then be used with the fields in the mandrill template to render the email.
The conversation object methods allow the creation of messages attached to a particular case.
-
arguments:
{Case} caseInstance
the case this conversation should be attached to.{object} attributes
a plain object with the data to create the conversation to attach tocaseInstance
. The attributes of this object are:{string} body
The contents of the message to post.{string} subject
The contents to show as the subject of the message.{[object|string]} recipients
An array of values that represent the recipients of the message. Each of its elements may take one of the 2 following values:- If it is an
object
, it must have the following attributes:{string} email
The email address of the recipient.{string} display_name
The name of the recipient.{string} type
One of the following 3 values: {'Users'
,'Teams'
,'Custom'
}, which mean the following:'Users'
refers to a recipient that is registered as one of the CaseBlocks account users. Setting this attribute to this value will default to sending the email message with theinternal_conversation
template.'Teams'
refers to a recipient that is a team, that is, a group of the account's CaseBlocks users. Setting this attribute to this value will default to sending the email message with theinternal_conversation
template.'Custom'
refers to a recipient that is not registered as one of the account's CaseBlocks users. Setting this attribute to this value will default to sending the email message with theexternal_conversation
template.
- If it is a
string
it must be the email address of the recipient. In this case, thediplay_name
used will be the email address itself and thetype
value of the recipient will be'Custom'
.
- If it is an
{[string]} attachments
A list ofDocument
instances' ids from those that belong to thecaseInstance
, which will be referenced as an attachment to the conversation message.{string} author_id
The id of the user on whose behalf this message should be posted.
-
returns:
{Promise.<object>}
A promise that resolves into a an object that represents theJSON
payload returned by the server, which contains information on the execution of the request.
Creates a conversation and attaches it to a case.
Caseblocks.Case.get('secret_agents', '09eef94cbc39370046000da1')
.then(caseInstance => {
const conversationAttributes = {
body: '<p>I have doubts about her loyalty.</p>'
subject: 'I have some doubts.'
recipients: [
{
display_name: The Boss
email: theboss@centralintelligence.gov,
type: 'Users'
},
'[email protected]'
],
attachments: [],
author_id: currentUser.id
}
return Conversation.create(caseInstance, conversationAttributes)
})
.then(response => {
// Handle response
})
.catch(err => {
// Handle error
})
You will find the existing specs under the test folder. HTTP calls are mocked in the spec_helper.js using nock file and you should add to this the calls and their results you expect to make.
npm test
Simples.
If this is the first time you are pushing to npm, you will need to setup your local npm first.
npm set init.author.name "Your Name"
npm set init.author.email "[email protected]"
npm set init.author.url "http://yourblog.com"
npm adduser
First task is to increment the version number in package.json. Increment the last number for small changes... eg 0.1.17 becomes 0.1.18.
"version": "0.1.18"
Save the file publish using the following command.
npm publish
In lieu of a formal styleguide, just assume the basic good practice of taking care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code.