Drag and drop a la trello?

  • 3
  • Idea
  • Updated 2 years ago
I'd rather not use any extra tools unless I have too. Trello looks pretty cool but it's outside Salesforce. Much of it can be reproduced in Skuid if only:

- records could be dragged from one component to another. Doing so would simply impose the component model conditions upon the record being dropped into it. Would be slick if the models used were based upon on the activities object.
- the order of the tasks could drag and drop
- related records could be dragged and dropped onto the task card. Ie. Assigned to or any other custom related objects

This would make for a really slick agile project management where we could customize it to our hearts content. Basically a skuidified trello.
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb

Posted 4 years ago

  • 3
Photo of Greg Jarrett

Greg Jarrett

  • 3,496 Points 3k badge 2x thumb
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
Ooooh! That's a good start. Only thing left would be drag and drop related records to the cards. ie. users
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,006 Points 20k badge 2x thumb
Pat,  we've done some additional work on this idea.  You can now select "popup" as the item select action on the queue.  This allows you to open more details for each item in your card list, including related lists.  I suppose that you could nest additional drag and drop queues in the popup, but things could get messy. 
Photo of Conlan O'Rourke

Conlan O'Rourke

  • 3,280 Points 3k badge 2x thumb
This Skuidified Trello concept looks amazing. I am contemplating incorporating it into a client onboarding/management process. Each time a new contact record is created, there are about 75 "tasks" that must be completed as part of the client management process.

Currently, these "tasks" are checkbox fields on the contact record. However, it looks like I would have to use a Queue component, requiring each of these "tasks" to be stored as individual child records.

Any ideas on how to have SF mass generate a standard set of task records when a new contact is created?
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
Hmmmm ... so many options to consider here. In order of which I would use.
  1. Skuid model cloning along maybe the need to use a snippet.
  2. Process Builder
  3. Flow
  4. Apex
Photo of Conlan O'Rourke

Conlan O'Rourke

  • 3,280 Points 3k badge 2x thumb
Thanks Pat. Could you provide more guidance/documentation on the model cloning option. I'm not too familiar with that concept.

Re: skuid solutions, I was also thinking about using either "Adopt Rows into Model" or "Create New Rows" actions...but given the number of records I would need to create, I'm worried about hitting some kind of limit or even the page taking forever to load. Do you think Skuid actions could handle creating that many records?

I had also initially thought of Process Builder, but again do you think it could handle creating 75 child records?
Photo of Jack Sanford

Jack Sanford, Champion

  • 8,322 Points 5k badge 2x thumb
One concept I've used again and again, not sure if it's the best but works for me:

Create a set of Task Template records. These could be a separate Record Type, a new custom object Task_Template__c, or just Tasks with a Type picklist field set to "Template".

Create a setup page for editing these Task Templates. Create your 75 records and all their details. 

Add a Model to your Contact creation page to bring in these Task Templates. Add another model for Tasks that will be created. This model should not pull in any data on page load, and it doesn't really need any conditions. You do need add fields corresponding to all the data you will copy from your Task Templates. 

Run a JavaScript snippet that looks through each of the rows in your TaskTemplate model and for each one found creates a new row in your Tasks model. You could run this from a button "Add Tasks", or even a model action "When new row created in Contact model" or "when Contact model saved", depends on your process. 

Here's a snippet that does this. The most I've created with it is about 35 rows, and it takes a few seconds to run. I think there should be a way to bulkify this so that each new row gets added to an array, and then you do the Create Row all at once at the end (or maybe you can use Adopt Rows? I think Adopt Rows will create a new row if there isn't a Record ID associated with it.)

I adapted this from someone else's post on the community a while back. h/t to them, wish I could remember who, I use this all the time. 

In the example below, substitute ConditionTemplates for  TaskTemplates, Conditions for Tasks, and Opportunity with Contact, or whatever your model names are. 

You could leave off the save part if you just wanted to create the rows and save them some other way. Like say you ran this snippet when the Contact model had a new created, you wouldn't want to save the Tasks until the Contact saves. 
var params = arguments[0],
	$ = skuid.$,
	models = skuid.model.map();
var dfd = new $.Deferred();

// model to add seleted rows from
var conditionTemplates = skuid.model.getModel('ConditionTemplates');
var rows = conditionTemplates.getRows();

// model to add to
var conditions = skuid.model.getModel('Conditions');

//other models
var oppModel = skuid.model.getModel('Opportunity');
var oppRow = oppModel.getFirstRow();
var oppId = oppModel.getFieldValue(oppRow,'Id');

// for each selected row, add a new row
$.each(rows, function(){

	
	// set variables for selected row field(s)
	var templateId = conditionTemplates.getFieldValue(this, 'Id');
	var templateName = conditionTemplates.getFieldValue(this, 'Name');
	var templateType = conditionTemplates.getFieldValue(this, 'Type__c');
	var templateDescription = conditionTemplates.getFieldValue(this, 'Description__c');
	var templateHelp = conditionTemplates.getFieldValue(this, 'Help__c');

	// create new row with selected row variables	
	var conditionRow = conditions.createRow({
		additionalConditions: [
			{field: 'ConditionTemplate__c', value: templateId, operator: '='},
			{field: 'Name__c', value: templateName, operator: '='},
			{field: 'Type__c', value: templateType, operator: '='},
			{field: 'Description__c', value: templateDescription, operator: '='},
			{field: 'Help__c', value: templateHelp, operator: '='},
			{field: 'Opportunity__c', value: oppId, operator: '='}
			
		]
	});
});
conditions.save({callback: function(result){
	if (result.totalsuccess) {
		//console.log(quotelines);
		dfd.resolve();
	} else {
		console.log(result.insertResults);
		console.log(result.updateResults);
		console.log(result.deleteResults);
		dfd.reject();
	}
}});


return dfd.promise();
Photo of Greg Jarrett

Greg Jarrett

  • 3,496 Points 3k badge 2x thumb
Hi Conlan,

We've done something similar to this in the past using an Apex Trigger and an object 'Template' - essentially the creation of these Task records is just a database operation, so doesn't necessarily require any interaction from the user.

The structure was like this:

The TaskTemplate__c object contained the 75 template/default records. This object has fields like Name, Description, Priority, Ref# and Active. The Active checkbox is useful to us because we occasionally need to de-activate a task item as we update our processes. And we can occasionally update the description or priority fields if we need to make changes to the process.

You then have a trigger on the Contact object which fires when the conditions are met for creating the task records. It iterates over each TaskTemplate__c Template record, and creates a real Task record attached to the Contact which fired the trigger.

That's just one approach.
Photo of Conlan O'Rourke

Conlan O'Rourke

  • 3,280 Points 3k badge 2x thumb
@Jack -- thanks so much for detailing this Skuid & JS snippet solution!

@Greg -- many thanks to you as well for detailing the Apex solution!

Either route we go, it sounds like the solution is essentially the same --> create a template object --> create all template task records, marking them "active" or not --> upon contact creation, run code that  iterates over the template object and creates the set of child task records to linked the contact record.

I will have to discuss with the client which route they prefer to go (Skuid or Apex Trigger). I'm not an Apex developer, so I'll have to get that quoted out, although I think I could handle the Skuid solution myself. My client has been debating the value add of Skuid licenses vs. cost...so this will be a perfect example of what it will cost to build this in Skuid vs. with an Apex trigger. My suspicion is that it will be significantly less expensive to have me do it in Skuid, plus they'll get the cool Trello board :)
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
Meh ... I prefer the following:

As per Jack, create a new Record Type on Task called Template. Then manage these Task templates using a custom Skuid page. You could even create a Set object to group them. Going even further you could create Set Task Assignment junction object between to assign Tasks to multiple Sets for reusability.

Then using the Clone option set to "Yes, Always" in a model you setup to query the templates to clone them. Then, you could simply do another action to update the Record Type to not be Template. Lastly, set the Tasks WhoId field to the Contact you have in mind. No javascript or apex required. Action 
  1. Show Message and block UI
  2. Create Row (NewContact)
  3. Query Model (TasksClone)
  4. Update a field on rows(s) (set RecordType Id as desired on TasksClone)
  5. Update a field on rows(s) (set WhoId to Contacts Id on TasksClone)
  6. Run a Skuid Javascript Snippet "setTemplateLookup" (optional)
  7. Save Models (NewContact & TasksClone)
  8. Unblock the UI

You could even create a Lookup from the new Tasks back to the Template tasks to track results & usage. This part would require a small snippet to set the values using a formula field I call GhostRecordId. You see, when cloning a record, the ids are temporarily assigned clone_#  and the # is incremented for each record cloned. So, if you would like to set the Template_Task__c lookup, it would be best if the original Id was available on the row itself. GhostRecordId with simply Id in the formula works perfectly, because when the model queries the Template Task, the GhostRecordId field will have the original Id value on the row. This way it's a simple loop in javascript to assign the value.

Now if you need these Tasks to be created when a Contact is created from more than one UI, then using Process and Flow would be the way to go, unless you Skuidify everywhere Contacts can be created. ie. Contact Tab, Contacts tab in Account Detail page, Salesforce1 Contacts Tab, etc. With PB and Flow, you can perform the same process as above all declaratively.

I tend to only use apex when all other options have been declared not suitable. Your use case doesn't require apex, but can be created by a good apex dev without any issue.

Lemeno if you would like to review the how-to on skype. pat.vachon.77
Photo of Conlan O'Rourke

Conlan O'Rourke

  • 3,280 Points 3k badge 2x thumb
Pat, this is awesome! I always love a no-code solution. The Lookup back to Template Tasks in order to track results and usage looks really cool. Let me take a stab at this, and I will let you know if I get stuck. 

Thanks!
Photo of Jack Sanford

Jack Sanford

  • 76 Points 75 badge 2x thumb
I had no idea about the Yes, Always clone option. Does Pat come up with a solution that blows my mind? Yes, Always. 
Photo of Jack Sanford

Jack Sanford

  • 76 Points 75 badge 2x thumb
Pat - how would you deal with duplicates? Like let's say if the create tasks was from a button, and maybe after the initial create someone added more Task Templates, is there a declarative way to remove all rows from the incoming Task Template model that match rows in the Existing Tasks model? Right now I'm using a snippet and Abandon Rows... I know there's an Abandon Context Row(s) in the Action Framework, but not sure how you'd tell skuid the context... 
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
Yes. Since the currently Tasks model would have a template id lookup, you could use this set of Ids as a Condition for the Template Tasks model. ie. Id - Not In - Field from Another Model - On. This way only Template Tasks that have yet to be created would be cloned.