This is a feature that came out without too much fanfare and was supposedly meant to address an idea. The only place that mentioned how to use it in Salesforce with details was in Summer '15 Release Notes, when it came out as beta. Then there's an article about using it with Community templates, in which it's referred as "Article Voting". None of them gives any clue on how it can be used in a Sites based Public Knowledge Base, which happens to be the use case I need to handle.
After some back and forth with Salesforce Support, they pointed me to this Developer Forum thread that talks about Vote object for Idea. I did some simple code to verify, and I could indeed set parentId to __ka objects and programmatically manipulate up/down vote state. That, was not mentioned at all in the official doc for the Vote object (as of Dec 2016, ver. 38.0).
With almost all the pieces in place, one hurdle remains for to a public KB Up/Down vote solution in VF/Apex, if the KB is used in an unauthenticated context. Vote object doesn't allow vote on the same parentId more than once by the same user. If the users are unauthenticated - basically always Public Site Guest User - then votes can't really be recorded for more than once. That's hardly useful. I have no workaround so far, other than building a custom solution without using Vote. That would suck if you'd really want internal and external votes are counted and reported together.
There must be a very good reason why we complicated our lives with all these technologies ... arguably that is freedom for something. Freedom might be a right but it is never free; so let me demonstrate how I earned it.
Showing posts with label APEX. Show all posts
Showing posts with label APEX. Show all posts
Monday, December 19, 2016
Monday, February 29, 2016
Apex code example for Kayako signature
Was looking at Kayako's API documentation - don't ask me why - and noticed there's no Apex example for their API request signature scheme (why would they?), so this might be useful for people who's in the same situation as I'm.
public class KayakoAPI {
public static string getSignature(string secretKey) {
string signature;
if (secretKey!=null && secretKey.length()>0) {
Blob salt = crypto.generateAesKey(128); //can use other ways for random string generation
// keyed hash
Blob hmacsha256 = crypto.generateMac('HmacSHA256', salt, Blob.valueOf(secretKey));
// Base64 and URL encoding
signature = EncodingUtil.urlEncode(EncodingUtil.base64Encode(hmacsha256), 'UTF-8');
}
return signature;
}
}
Friday, February 7, 2014
Converting DateTime to Date in Apex: Undocumented Pitfall
All roads lead to Rome... almost. There's more than one way to do the conversion in Apex, and they yield subtle but meaningful differences. Consider these two statements:
system.debug(Date.Valueof(DateTime.valueof('2014-02-06 21:11:11')));
system.debug(DateTime.valueof('2014-02-06 21:11:11').date());
Both on the surface do an explicit type cast from DateTime to Date, but the results are different. An important note: I ran them as an Eastern Time Zone user. Here are the results:
10:12:51.045 (45992000)|USER_DEBUG|[8]|DEBUG|2014-02-07 02:11:11
10:12:51.046 (46064000)|USER_DEBUG|[9]|DEBUG|2014-02-06 00:00:00
Semantically the second statement has the right answer: as a user in EST, I expect to get the date in my time zone, which should be Feb 6th. The first one seems to supply a GMT date. Also note it still has the time part. Weird.
The catch here is, Date.valueOf(DateTime) doesn't exist in the official documentation. Date.valueOf(Object) does exist, but that's meant to be used only with history tracking values. Since it's not officially supported, I guess you can't blame Salesforce officially for the unexpected result.
I didn't use the undocumented method on purpose - I just did it assuming it's there. Apex, after all, is only almost strongly typed, because we don't have well-documented rules for type casting. I crossed the boundary, and I was on my own. Well, it wasn't that bad - it just cost me some extra time to figure out why the hell the test failed at night, when it ran flawlessly during the day.
system.debug(Date.Valueof(DateTime.valueof('2014-02-06 21:11:11')));
system.debug(DateTime.valueof('2014-02-06 21:11:11').date());
Both on the surface do an explicit type cast from DateTime to Date, but the results are different. An important note: I ran them as an Eastern Time Zone user. Here are the results:
10:12:51.045 (45992000)|USER_DEBUG|[8]|DEBUG|2014-02-07 02:11:11
10:12:51.046 (46064000)|USER_DEBUG|[9]|DEBUG|2014-02-06 00:00:00
Semantically the second statement has the right answer: as a user in EST, I expect to get the date in my time zone, which should be Feb 6th. The first one seems to supply a GMT date. Also note it still has the time part. Weird.
The catch here is, Date.valueOf(DateTime) doesn't exist in the official documentation. Date.valueOf(Object) does exist, but that's meant to be used only with history tracking values. Since it's not officially supported, I guess you can't blame Salesforce officially for the unexpected result.
I didn't use the undocumented method on purpose - I just did it assuming it's there. Apex, after all, is only almost strongly typed, because we don't have well-documented rules for type casting. I crossed the boundary, and I was on my own. Well, it wasn't that bad - it just cost me some extra time to figure out why the hell the test failed at night, when it ran flawlessly during the day.
Labels:
APEX,
conversion,
Date,
DateTime,
Salesforce,
type cast,
valueOf
Wednesday, January 29, 2014
MIME type for Test.loadData()
Test.loadData() is a convenient way to create a bunch of test data for test methods in Apex. Without it (which was not long ago) you basically resorted to an unsightly long piece of code if you have a complex test data environment to create. I suspected that's one of the reasons people abused the SeeAllData attribute.
With loadData(), however, I sometimes ran into an issue with the static resource required by the call. According to the documentation, it supports four kinds of MIME types for the resource used:
The only way to remedy the situation seems to be using something Metadata API based (say Force.com IDE) to manually edit the MIME type to text/csv, after which it would work fine. That's a bit of annoyance when all you need is to quickly whip out the data file with Notepad++ but ended up spending 10 minutes to get the type right, almost just as long as writing those boring insert statements. So there's an idea out there to make MIME type editable on static resources, which I think everyone who uses loadData() should vote for.
With loadData(), however, I sometimes ran into an issue with the static resource required by the call. According to the documentation, it supports four kinds of MIME types for the resource used:
- text/csv
- application/vnd.ms-excel
- application/octet-stream
- text/plain
The only way to remedy the situation seems to be using something Metadata API based (say Force.com IDE) to manually edit the MIME type to text/csv, after which it would work fine. That's a bit of annoyance when all you need is to quickly whip out the data file with Notepad++ but ended up spending 10 minutes to get the type right, almost just as long as writing those boring insert statements. So there's an idea out there to make MIME type editable on static resources, which I think everyone who uses loadData() should vote for.
Wednesday, February 2, 2011
Client side vs. server side on Visualforce
What I needed to do was to disable a drop down box based on the selection in another drop down. Fairly common requirement. The controller drop down starts as disabled, so I set disabled property in , and used JavaScript from onchange to toggle disabled in HTML DOM from the controlling drop down. All sounded fine and dandy and the UI worked as it should, until I realized that the form never returned anything from the controlled drop down no matter what its status was.
It looks like the client side JavaScript did nothing to enable the controlled element. As far as the server was concerned, it's a field it can discard. I didn't do any HTML/JS debugging to confirm that, but it certainly felt that way. Once I switched the controlling mechanism to server-side processing/AJAX, it started to work as intended.
The only drawback with the AJAX way was that it's a bit slower. Action from the client-side Javascript was instant. With AJAX and its server round trip, it took about one second for the controlled drop down to change status.
It looks like the client side JavaScript did nothing to enable the controlled element. As far as the server was concerned, it's a field it can discard. I didn't do any HTML/JS debugging to confirm that, but it certainly felt that way. Once I switched the controlling mechanism to server-side processing/AJAX, it started to work as intended.
The only drawback with the AJAX way was that it's a bit slower. Action from the client-side Javascript was instant. With AJAX and its server round trip, it took about one second for the controlled drop down to change status.
Wednesday, August 4, 2010
Apex Explorer for Force.com: using newer API
It's a handy tool but the newest version available uses API 8.0. Can't remember when that one came out. :) So I tried to change the Options to use newer APIs. The newest version I can get to is 16.0. Beyond that it pops a "null reference" error and is unable to retrieve object list. So there's no change for anything new in API 17, 18, and 19, and I suspect a lot of things in versions after 8 don't get used either.
Subscribe to:
Posts (Atom)
